前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >过山车(匈牙利算法)- HDU 2063

过山车(匈牙利算法)- HDU 2063

作者头像
ACM算法日常
发布2018-09-21 17:22:52
8860
发布2018-09-21 17:22:52
举报
文章被收录于专栏:ACM算法日常

Problem Description

RPG girls今天和大家一起去游乐场玩,终于可以坐上梦寐以求的过山车了。可是,过山车的每一排只有两个座位,而且还有条不成文的规矩,就是每个女生必须找个个男生做partner和她同坐。但是,每个女孩都有各自的想法,举个例子把,Rabbit只愿意和XHD或PQK做partner,Grass只愿意和linle或LL做partner,PrincessSnow愿意和水域浪子或伪酷儿做partner。考虑到经费问题,boss刘决定只让找到partner的人去坐过山车,其他的人,嘿嘿,就站在下面看着吧。聪明的Acmer,你可以帮忙算算最多有多少对组合可以坐上过山车吗?

Input

输入数据的第一行是三个整数K , M , N,分别表示可能的组合数目,女生的人数,男生的人数。0<K<=1000 1<=N 和M<=500.接下来的K行,每行有两个数,分别表示女生Ai愿意和男生Bj做partner。最后一个0结束输入。

Output

对于每组数据,输出一个整数,表示可以坐上过山车的最多组合数。

Sample Input

代码语言:javascript
复制
6 3 3

Sample Output

代码语言:javascript
复制
3

匈牙利算法:

算法的核心就是根据一个初始匹配不停的找增广路,直到没有增广路为止。

匈牙利算法的本质实际上和基于增广路特性的最大流算法还是相似的,只需要注意两点:

(一)每个X节点都最多做一次增广路的起点;

(二)如果一个Y节点已经匹配了,那么增广路到这儿的时候唯一的路径是走到Y节点的匹配点

找增广路的时候既可以采用dfs也可以采用bfs,两者都可以保证O(nm)的复杂度,因为每找一条增广路的复杂度是O(m),而最多增广n次,dfs在实际实现中更加简短。

匈牙利算法的基本模式:

1、 初始时最大匹配为空

2、 while (找得到增广路径)

3、 do 把增广路径加入到最大匹配中。

如果二分图的左半边一共有n个点,最多找n条增广路径,如果图中有m条边,每一条增广路径把所有边遍历一遍,所以时间复杂度为O(n*m);

算法思想:

算法的思路是不停的找增广轨, 并增加匹配的个数,增广轨顾名思义是指一条可以使匹配数变多的路径,在匹配问题中,增广轨的表现形式是一条"交错轨",也就 是说这条由图的边组成的路径, 它的第一条边是目前还没有参与匹配的,第二条边参与了匹配,第三条边没有..最后一条边没有参与匹配,并且始点和终点还没 有被选择过.这样交错进行,显然 他有奇数条边.那么对于这样一条路径,我们可以将第一条边改为已匹配,第二条边改为未匹配...以此类推.也就是将所有 的边进行"反色",容易发现这样修 改以后,匹配仍然是合法的,但是匹配数增加了一对.另外,单独的一条连接两个未匹配点的边显然也是交错轨.可以证明, 当不能再找到增广轨时,就得到了一个 最大匹配.这也就是匈牙利算法的思路。

二分图匹配中较为重要的三个公式:

二分图最小顶点覆盖 = 二分图最大匹配;

DAG图的最小路径覆盖 = 节点数(n)- 最大匹配数;

二分图最大独立集 = 节点数(n)- 最大匹配数;

源代码:

代码语言:javascript
复制
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1e3+10;
int n1,n2,k;
//n1,n2为二分图的顶点集,其中x属于n1,y属于n2
int map[maxn][maxn],vis[maxn],link[maxn];
//link记录n2中的点y在n1中所匹配的x点的编号
void init()
{
    memset(map,0,sizeof map);
    memset(link,0,sizeof link);
}
int find(int x)
{
    for(int i=1;i<=n2;i++)
    {
        if(map[x][i]&&!vis[i])//x->i有边,且节点i未被搜索
        {
            vis[i]=1;//标记节点已经被搜索
            //如果i不属于前一个匹配M,或被i匹配到的节点可以寻找到增广路
            if(link[i]==0||find(link[i]))
            {
                link[i]=x;//更新
                return 1;//匹配成功
            }
        }
    }
    return 0;
}
int main()
{
    while(~scanf("%d",&k)&&k){
        scanf("%d%d",&n1,&n2);
        init();
        for(int i=0;i<k;i++)
        {
             int x,y;
            scanf("%d%d",&x,&y);
            map[x][y]=1;
        }
        int ans=0;
        for(int i=1;i<=n1;i++)
        {
            memset(vis,0,sizeof vis);
            if(find(i)) ans++;
        }
        printf("%d\n",ans);
    }
   return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-09-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ACM算法日常 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Problem Description
  • RPG girls今天和大家一起去游乐场玩,终于可以坐上梦寐以求的过山车了。可是,过山车的每一排只有两个座位,而且还有条不成文的规矩,就是每个女生必须找个个男生做partner和她同坐。但是,每个女孩都有各自的想法,举个例子把,Rabbit只愿意和XHD或PQK做partner,Grass只愿意和linle或LL做partner,PrincessSnow愿意和水域浪子或伪酷儿做partner。考虑到经费问题,boss刘决定只让找到partner的人去坐过山车,其他的人,嘿嘿,就站在下面看着吧。聪明的Acmer,你可以帮忙算算最多有多少对组合可以坐上过山车吗?
  • 匈牙利算法:
    • 匈牙利算法的基本模式:
      • 算法思想:
        • 二分图匹配中较为重要的三个公式:
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档