hdu 3081 二分匹配

来源:互联网 发布:js验证是否是数字 编辑:程序博客网 时间:2024/04/28 17:18

题目:http://acm.hdu.edu.cn/showproblem.php?pid=3081

题意:

        给出一些女孩喜欢的男孩,并且这些女孩朋友喜欢的男孩,她也可以喜欢;问这些女孩在不重复挑选男孩过家家的情况下,能挑选几轮(每个女孩不能挑选之前挑选过的男孩)

解法:

         用floyd 拓扑整个图,然后用匈牙利算法求出最大二分匹配,如果二分匹配数==女孩数,那么这一轮游戏成功进行,之后删除这些匹配边!!!重复执行上一部!!

代码:

#include<iostream>#include<cstdio>#include<algorithm>#include<memory.h>using namespace std;const int maxn=102;int n,m,fri,t,ans,res,a,b,f[maxn][maxn];int map[maxn][maxn],vis[maxn],mat[maxn];void floyd(){     for(int k=1; k<=n; k++)    {        for(int i=1; i<=n; i++)        {            if(map[i][k])            for(int j=1; j<=n; j++)            {                if(map[k][j]) map[i][j]=1;            }        }    }    for(int k=1; k<=n; k++)    {        for(int i=1; i<=n; i++)        {            if(map[i][k])            for(int j=1; j<=n; j++)            {                if(f[k][j]) f[i][j]=1;            }        }    }}int find(int x){    for(int i=1; i<=n; i++)    {        if(f[x][i]&&!vis[i])        {            vis[i]=1;            if(mat[i]==-1||find(mat[i]))            {                mat[i]=x;                return 1;            }        }    }    return 0;}int main(){    scanf("%d",&t);    while(t--)    {        scanf("%d%d%d",&n,&m,&fri);        memset(f,0,sizeof(f));        memset(map,0,sizeof(map));        for(int i=1; i<=m; i++)        {            scanf("%d%d",&a,&b);            f[a][b]=1;        }        for(int i=1; i<=fri; i++)        {            scanf("%d%d",&a,&b);            map[a][b]=1,map[b][a]=1;        }        floyd(); res=0;        while(1)        {            ans=0;            memset(mat,-1,sizeof(mat));            for(int i=1; i<=n; i++)            {                memset(vis,0,sizeof(vis));                if(find(i)) ans++;            }            if(ans==n) res++;            else break;            for(int i=1;i<=n;i++)            {                //if(mat[i]>0)                f[mat[i]][i]=0;            }        }        printf("%d\n",res);    }    return 0;}

原创粉丝点击