HDU 2063:过山车(匈牙利算法模板题)

过山车

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 17836    Accepted Submission(s): 7779


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
 


最小点覆盖数:假如选了一个点就相当于覆盖了以它为端点的所有边,你需要选择最少的点来覆盖所有的边

独立集:图中任意两个顶点都不相连的顶点集合

交替路:从一个未匹配点出发,依次经过非匹配边、匹配边、非匹配边…形成的路径叫交替路。

增广路:从一个未匹配点出发,走交替路,如果途径另一个未匹配点(出发的点不算),则这条交替路称为增广路

定理1:二分图最大匹配==最小点覆盖数

定理2:顶点数-二分图最大匹配==最大独立集

定理3:最大匹配是增广路不存在的充要条件


匈牙利算法:

解决问题→二分图最大匹配,本质DFS,复杂度V*E


#include<stdio.h>
#include<string.h>
int k, n, m, road[505][505], vis[505], link[505];
int Sech(int x);
int main(void)
{
	int i, a, b, ans;
	while(scanf("%d", &k), k!=0)
	{
		ans = 0;
		scanf("%d%d", &n, &m);
		memset(road, 0, sizeof(road));
		memset(link, 0, sizeof(link));
		for(i=1;i<=k;i++)
		{
			scanf("%d%d", &a, &b);		/*road[a][b]==1表示第a个男生对第b个女生有好感,否则没有*/
			road[a][b] = 1;
		}
		for(i=1;i<=n;i++)		/*算法思路:从第一个男生开始,尽可能让每个男生匹配成功,或是还有心仪的女生名花无主直接匹配,或是调整前面已有的匹配已达到找到自己心仪的女生*/
		{
			memset(vis, 0, sizeof(vis));	/*vis为标记数组,vis[k]==1表示第k个女生已经被查找过并试图改变过该妹子的归属问题,没有必要再次查找*/
			if(Sech(i)==1)		/*第i个男生匹配成功*/
				ans++;
		}
		printf("%d\n", ans);
	}
	return 0;
}

int Sech(int x)
{
	int i;
	for(i=1;i<=m;i++)	/*对于每个男生,先枚举每一个女生*/
	{
		if(vis[i]==0 && road[x][i]==1)		/*如果这个女生还未被查找且这个男生对这个女生有好感*/
		{
			vis[i] = 1;		/*标记*/
			if(link[i]==0 || Sech(link[i])==1)		/*如果这个女生名花无主或是可以腾出个位置*/
			{			/*这其实是一个寻找增广路的过程*/
				link[i] = x;		/*恭喜这一对男女配对成功*/
				return 1;
			}
		}
	}
	return 0;
}


  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值