您的位置:首页 > 其它

hdu 3081 Marriage Match II【并查集+二分匹配---匈牙利】

2016-08-03 14:45 806 查看

Marriage Match II

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3583    Accepted Submission(s): 1163


Problem Description

Presumably, you all have known the question of stable marriage match. A girl will choose a boy; it is similar as the game of playing house we used to play when we are kids. What a happy time as so many friends playing together. And it is normal that a fight
or a quarrel breaks out, but we will still play together after that, because we are kids. 

Now, there are 2n kids, n boys numbered from 1 to n, and n girls numbered from 1 to n. you know, ladies first. So, every girl can choose a boy first, with whom she has not quarreled, to make up a family. Besides, the girl X can also choose boy Z to be her boyfriend
when her friend, girl Y has not quarreled with him. Furthermore, the friendship is mutual, which means a and c are friends provided that a and b are friends and b and c are friend. 

Once every girl finds their boyfriends they will start a new round of this game—marriage match. At the end of each round, every girl will start to find a new boyfriend, who she has not chosen before. So the game goes on and on.

Now, here is the question for you, how many rounds can these 2n kids totally play this game?

Input

There are several test cases. First is a integer T, means the number of test cases. 

Each test case starts with three integer n, m and f in a line (3<=n<=100,0<m<n*n,0<=f<n). n means there are 2*n children, n girls(number from 1 to n) and n boys(number from 1 to n).

Then m lines follow. Each line contains two numbers a and b, means girl a and boy b had never quarreled with each other. 

Then f lines follow. Each line contains two numbers c and d, means girl c and girl d are good friends.

Output

For each case, output a number in one line. The maximal number of Marriage Match the children can play.

Sample Input

1

4 5 2

1 1

2 3

3 2

4 2

4 4

1 4

2 3

Sample Output

2

 

题目大意:有n*2个小孩,其中有n个女孩,有n个男孩,这些小孩玩过家家游戏,女孩只选择和自己没吵过架的,或者是没和自己朋友吵过架的男孩子一起过家家,每一轮每个女孩都必须找一个男孩过家家,下一轮就不能选择之前自己选过的男孩进行过家家游戏,问最多能玩多少轮。

输入:t,表示组数,接下来三个元素,分别表示有n对小孩,有m对男女孩么有吵过架,有f对朋友,接下来m行,每行两个元素,a,b表示a女孩和b男孩没有吵过架,接下来f行,每行两个元素a,b表示a女孩和b女孩是朋友。

思路:

1、首先建图,设定map【i】【j】表示女孩i可以选择男孩j过家家。

①因为女孩可以选择的男孩有两种:一种是其朋友可以选择的男孩,一种是和自己没有吵过架的男孩,第二种可以直接在输入的时候就处理,而第一种,我们可以通过多种方式来解决,这里我们来尝试用并查集搞定这个问题,在输入f对朋友关系的时候,我们将是朋友关系的两个人加入一个集合中,然后N^2枚举i,j女孩,如果i,j在一个集合中,那么再用一层for同步两个人能够选择的男孩。{(ifmap【i】【k】==1)map【j】【k】=1}时间复杂度O(N^3)因为N并不大,所以还是能够撑得住的。

2、然后我们处理能够玩多少轮的问题,看到网上各种题解很多人都用二分+最大流来搞。一会也尝试做一下,这里其实我们可以暴力,一共N个男孩,N个女孩,无非最多也就玩N轮游戏,我们不妨使用匈牙利二分匹配算法,从而来判断当前情况能否组成一轮游戏,如果可以组成一轮游戏,那么对应map【match【i】】【i】=0置为0,表示这一轮游戏,女孩match【i】选择了编号为i的男孩,以后就不能一起过家家了,因为已经过过了、然后每次达到完全匹配的时候,我们就对应ans++。直到不能达到完全匹配为止,时间复杂度O(N^3){邻接表}或者O(N^2M){邻接表}

3、那么整体时间复杂度:O(N^3),显然不会超时。接下来就是实现代码、

Ac代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int f[215];
int map[215][215];
int vis[251];
int match[251];
int n,c,d;
int find(int a)
{
int r=a;
while(f[r]!=r)
r=f[r];
int i=a;
int j;
while(i!=r)
{
j=f[i];
f[i]=r;
i=j;
}
return r;
}
void merge(int a,int b)
{
int A,B;
A=find(a);
B=find(b);
if(A!=B)
f[B]=A;
}
int Dfs(int u)
{
for(int i=1;i<=n;i++)
{
if(vis[i]==0&&map[u][i])
{
vis[i]=1;
if(match[i]==-1||Dfs(match[i]))
{
match[i]=u;
return 1;
}
}
}
return 0;
}
void Slove()
{
int ans=0;
while(1)
{
memset(match,-1,sizeof(match));
int tmp=0;
for(int j=1;j<=n;j++)
{
memset(vis,0,sizeof(vis));
if(Dfs(j))tmp++;
}
if(tmp==n)
{
for(int j=1;j<=n;j++)
{
map[match[j]][j]=0;
}
}
else break;
ans++;
}
printf("%d\n",ans);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(map,0,sizeof(map));
for(int i=1;i<=215;i++)f[i]=i;
scanf("%d%d%d",&n,&c,&d);
for(int i=0;i<c;i++)
{
int x,y;
scanf("%d%d",&x,&y);
map[x][y]=1;
}
for(int i=0;i<d;i++)
{
int x,y;
scanf("%d%d",&x,&y);
merge(x,y);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(find(i)==find(j))
{
for(int k=1;k<=n;k++)
{
if(map[i][k]==1)
{
map[j][k]=1;
}
if(map[j][k]==1)
{
map[i][k]=1;
}
}
}
}
}
Slove();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hdu 3081 杭电 3081