ZOJ 3642 Just Another Information Sharing Problem【二分图多重匹配】
题意: 有N 个人,知道了每个人知道的信息,和它最多能告诉别人的信息数目,问编号为 m 的人最多能知道的信息条数是多少。
分析: 由于信息的编号比较大,所以先需要进行离散化。
每个人和自己知道的每个信息之间都有一条边相连,
每个人匹配容量为 他最多能告诉别人的信息数目。
#include<stdio.h> #include<string.h> #define maxn 222 #define clr(x)memset(x,0,sizeof(x)) int cap[maxn]; int map[maxn][maxn]; int vlink[maxn]; int link[maxn][maxn]; //link[i][j] 表示与i点匹配好的第j个点 int v[maxn]; int n,m; int find(int x) { int i,j; for(i=0;i<n;i++) { if(map[x][i]&&!v[i]) { v[i]=1; if(vlink[i]<cap[i]) //i点的匹配数尚未达到上限,可直接匹配 { link[i][vlink[i]++]=x; //x做为i的第vlink[i]个匹配点 return 1; } //如果i点的匹配数已经达到上限,则遍历之前与i匹配的点 for(j=0;j<vlink[i];j++) //若它能与别的点匹配,则将位置让出来给 x { if(find(link[i][j])) //能与其他点匹配 { link[i][j]=x; //让出位置给 x return 1; } } } } return 0; } int man[maxn][maxn]; int tt[maxn]; int vis[1000005]; int main() { int i,j,flag,p,mm,tot,cc,res; while(scanf("%d",&n)!=EOF) { clr(tt); clr(vis); tot=1; for(i=0;i<n;i++) { scanf("%d%d%d",&mm,&p,&cap[i]); while(mm--) { scanf("%d",&p); if(vis[p]==0) vis[p]=tot++; man[i][tt[i]++]=vis[p]; } } memset(vlink,0,sizeof(vlink)); scanf("%d",&cc); cap[cc-1]=222; clr(map); for(i=0;i<n;i++) for(j=0;j<tt[i];j++) map[man[i][j]][i]=1; m=tot-1; int res=0; for(i=1;i<=m;i++) { memset(v,0,sizeof(v)); if(find(i)) res++; } printf("%d\n",res); } return 0; }