hdu 1068 二分匹配 匈牙利算法

来源:互联网 发布:淘宝美工需要做着什么 编辑:程序博客网 时间:2024/06/09 23:37

题意:

    给出孩子们的联系,并且只有男孩和女孩间会产生暧昧,问最多有多少孩子间没有暧昧关系!!

思路:

          最大独立集点数 = N - 最大匹配数

解法:

      匈牙利算法:

算法的思路是不停的找增广轨,并增加匹配的个数,增广轨顾名思义是指一条可以使匹配数变多的路径,在匹配问题中,增广轨的表现形式是一条"交错轨",也就是说这条由图的边组成的路径,它的第一条边是目前还没有参与匹配的,第二条边参与了匹配,第三条边没有..最后一条边没有参与匹配,并且始点和终点还没有被选择过.这样交错进行,显然他有奇数条边.那么对于这样一条路径,我们可以将第一条边改为已匹配,第二条边改为未匹配...以此类推.也就是将所有的边进行"反色",容易发现这样修改以,匹配仍然是合法的,但是匹配数增加了一对.另外,单独的一条连接两个未匹配点的边显然也是交错轨.可以证明,当不能再找到增广轨时,就得到了一个最大匹配.这也就是匈牙利算法的思路.
邻接表代码:
#include<iostream>#include<cstdio>#include<algorithm>#include<memory.h>using namespace std;const int maxn=1002;int f[maxn][maxn],mat[maxn],vis[maxn],n;//邻接表 实现匈牙利算法int idx,num,link;int find(int x){    for(int i=f[x][0]; i>=1; i--)    {        int y=f[x][i];        if(!vis[y])        {            vis[y]=1;            if(mat[y]==-1||find(mat[y]))            {                mat[y]=x;                return 1;            }        }    }    return 0;}int main(){    int i,j,k,ans;    while(scanf("%d",&n)!=EOF)    {        memset(f,0,sizeof(f));        memset(mat,-1,sizeof(mat));        ans=0;        for(i=0; i<n; i++)        {            scanf("%d: (%d)",&idx,&num);            for(j=0; j<num; j++)            {                scanf("%d",&link);                f[idx][++f[idx][0]]=link;            }        }        for(i=0; i<n; i++)        {            memset(vis,0,sizeof(vis));            if(find(i)) ans++;        }        printf("%d\n",n-ans/2);    }    return 0;}


原创粉丝点击