您的位置:首页 > 其它

【HDU】3081 Marriage Match II

2016-07-28 11:32 295 查看

Marriage Match II

题目链接

Marriage Match II

题目大意

n个女生n个男生玩过家家~满足如下2个条件即可组成一对:

女生a没和男生b吵过架

女生a的朋友c没和男生b吵过架

每个人都配对之后就继续玩下一轮,但是下一轮中每个人都必须选择一个另外的人配对,现在问最多玩多少轮。

题解

二分图 并查集

我们可以看到如果a的朋友b能和c配对,那么a也能和c配对,所以我们先用并查集处理出女生的朋友集合,然后对于每两个女生和男生的情况处理出所有的边。最后对整个图求最大匹配,当最大匹配与n相等的时候,先删去当前匹配边,再继续求最大匹配,当某个时刻最大匹配和n不相等,此时循环的次数就是答案。

代码

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

int T,n,m,f,b,a;
int g[105][105],link[105],father[105];
bool vis[105];

int getfather(int k)
{
if (father[k]==k) return k;
return father[k]=getfather(father[k]);
}

bool dfs(int u)
{
for (int i=1;i<=n;i++) if (!vis[i] && g[u][i])
{
vis[i]=1;
if (!link[i] || dfs(link[i]))
{
link[i]=u;
return 1;
}
}
return 0;
}

int solve()
{
int ans=0;
memset(link,0,sizeof(link));
for (int i=1;i<=n;i++)
{
memset(vis,0,sizeof(vis));
if (dfs(i)) ans++;
}
for (int i=1;i<=n;i++) if (link[i]) g[link[i]][i]=0;
return ans;
}

int main()
{
scanf("%d",&T);
while (T--)
{
for (int i=0;i<105;i++) father[i]=i;
memset(g,0,sizeof(g));
scanf("%d%d%d",&n,&m,&f);
for (int i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
g[a][b]=1;
}
for (int i=0;i<f;i++)
{
scanf("%d%d",&a,&b);
int fa,fb;
fa=getfather(a); fb=getfather(b);
if (fa!=fb) father[fa]=fb;
}
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
{
int f1,f2;
f1=getfather(i);
f2=getfather(j);
if (f1==f2) for (int k=1;k<=n;k++) if (g[i][k]) g[j][k]=1;
}
int ans=0;
while (solve()==n) ans++;
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: