您的位置:首页 > 理论基础 > 计算机网络

HDU2063-过山车(二分匹配 +匈牙利算法)

2018-02-02 16:20 302 查看
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

6 3 3
1 1
1 2
1 3
2 1
2 3
3 1
0

 

Sample Output

3

 

地址:点击打开链接

思路:

就是通过匈牙利算法模板来求解问题,下面简单介绍一下匈牙利算法:

匈牙利算法的实际是网络流思想,核心是寻找增广路。

下面简单描述一下算法:

以下转自:点击打开链接

通过数代人的努力,你终于赶上了剩男剩女的大潮,假设你是一位光荣的新世纪媒人,在你的手上有N个剩男,M个剩女,每个人都可能对多名异性有好感(

-_-||暂时不考虑特殊的性取向),如果一对男女互有好感,那么你就可以把这一对撮合在一起,现在让我们无视掉所有的单相思(好忧伤的感觉

),你拥有的大概就是下面这样一张关系图,每一条连线都表示互有好感。



本着救人一命,胜造七级浮屠的原则,你想要尽可能地撮合更多的情侣,匈牙利算法的工作模式会教你这样做:

===============================================================================

一: 先试着给1号男生找妹子,发现第一个和他相连的1号女生还名花无主,got it,连上一条蓝线



===============================================================================

:接着给2号男生找妹子,发现第一个和他相连的2号女生名花无主,got it



===============================================================================

:接下来是3号男生,很遗憾1号女生已经有主了,怎么办呢?

我们试着给之前1号女生匹配的男生(也就是1号男生)另外分配一个妹子。

(黄色表示这条边被临时拆掉)



与1号男生相连的第二个女生是2号女生,但是2号女生也有主了,怎么办呢?我们再试着给2号女生的原配(



)重新找个妹子(注意这个步骤和上面是一样的,这是一个递归的过程)



此时发现2号男生还能找到3号女生,那么之前的问题迎刃而解了,回溯回去

2号男生可以找3号妹子~~~                  1号男生可以找2号妹子了~~~                3号男生可以找1号妹子







所以第三步最后的结果就是:



===============================================================================

: 接下来是4号男生,很遗憾,按照第三步的节奏我们没法给4号男生腾出来一个妹子,我们实在是无能为力了……香吉士同学走好。

===============================================================================

这就是匈牙利算法的流程,其中找妹子是个递归的过程,最最关键的字就是“腾”字

其原则大概是:有机会上,没机会创造机会也要上

代码:#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
int line[510][510],boy[510],used[510];
int n,m;
int Find(int x)
{
int i,j;
for(i=1;i<=m;i++)//遍历所有被选者
{
if(line[x][i]==1&&used[i]==0)
{//如果 x对i有好感且在这一个递归选取阶段没有被选取(哪怕是暂时选取,新的递归可能会换)
used[i]=1;//标记被选取
if(boy[i]==0||Find(boy[i]))//如果被选者没有归属或他的归属着可以调换(他的归属者可以选择其它被选者)
{
boy[i]=x;//将归属定为 x
return 1;
}
}
}
return 0;
}
int main()
{
int i,j,k,x,y,sum;
while(scanf("%d %d %d",&k,&n,&m),k!=0)
{
memset(line,0,sizeof(line));
memset(boy,0,sizeof(boy));
memset(used,0,sizeof(used));
for(i=0;i<k;i++)
{
scanf("%d %d",&x,&y);
line[x][y]=1;//表示 x希望与 y有关系
}
sum=0;//记录能撮合的情侣对数
for(i=1;i<=n;i++)
{
memset(used,0,sizeof(used));//每次都要清 0
if(Find(i)) sum++;//找到一对就记录
}
printf("%d\n",sum);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息