【HDU】3081 Marriage Match II

来源:互联网 发布:木雕机编程 编辑:程序博客网 时间:2024/06/11 09:31

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;}
0 0
原创粉丝点击