POJ-2289 Jamie's Contact Groups
阿新 • • 發佈:2018-12-16
二分圖多重匹配+二分
對於每個組設定匹配上限,然後用二分圖多重匹配看能否全部匹配好
直到找到最小的上限,這就是最大的組的最小值,這個過程可以用二分來優化
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #include<sstream> using namespace std; typedef long long ll; const int N=1000+10; const int M=500+10; const int INF=0x7f7f7f7f; int uN,vN; int g[N][M]; int linker[N][M]; bool used[M]; int num[M]; bool dfs(int u) { for(int v=0;v<vN;v++) if(g[u][v]&&!used[v]) { used[v]=true; if(linker[v][0]<num[v]) { linker[v][++linker[v][0]]=u; return true; } for(int i=1;i<=num[0];i++) if(dfs(linker[v][i])) { linker[v][i]=u; return true; } } return false; } int hungary() { int res=0; for(int i=0;i<vN;i++) linker[i][0]=0; for(int u=0;u<uN;u++) { memset(used,false,sizeof(used)); if(dfs(u)) res++; } return res; } int main() { int n,m; while(~scanf("%d%d",&n,&m)) { if(n==0&&m==0) break; getchar(); memset(g,0,sizeof(g)); for(int i=0;i<n;i++) { string s; stringstream ss; getline(cin,s); ss<<s; ss>>s; int a; while(ss>>a) g[i][a]=1; } uN=n;vN=m; int ans=n,l=1,r=n; while(l<r) { int m=(l+r)>>1; for(int v=0;v<vN;v++) num[v]=m; int num=hungary(); if(num<n) { l=m+1; } else { r=m; ans=m; } } int m=(l+r)>>1; memset(num,m,sizeof(num)); int num=hungary(); if(num==n) ans=m; printf("%d\n",ans); } return 0; }