UVA 1345 Jamie's Contact Groups(二分+最大流)
阿新 • • 發佈:2018-12-18
題意:有n個人,m個組,給出每個人想要去的分組,每個人只能去一個組,問人數最多的那個組最少有多少個人
二分一下每個組的可以放的人數,然後每個組與匯點相連,容量為二分的值,源點與每個人相連,容量為1,每個人與想去的組連邊,容量為1,跑一邊最大流判斷即可
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<vector> #include<sstream> using namespace std; const int maxn=2010; const int maxm=1e6+7; const int inf=0x3f3f3f3f; #define pb push_back struct Node { int to; int capa; int next; }edge[maxm]; int n,m; int source,sink; int cnt; int head[maxn]; bool vis[maxn]; int dep[maxn]; char name[100010]; vector<int> vec[maxn]; void init() { memset(head,-1,sizeof(head)); cnt=0; return; } void add(int u,int v,int capa) { edge[cnt].to=v; edge[cnt].capa=capa; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].to=u; edge[cnt].capa=0; edge[cnt].next=head[v]; head[v]=cnt++; return; } bool bfs() { queue<int> que; que.push(source); memset(dep,-1,sizeof(dep)); dep[source]=0; while(!que.empty()) { int node=que.front(); que.pop(); for(int i=head[node];~i;i=edge[i].next) { int v=edge[i].to; if(edge[i].capa>0&&dep[v]==-1) { dep[v]=dep[node]+1; if(v==sink) return true; que.push(v); } } } return dep[sink]!=-1; } int dfs(int node,int minn) { if(node==sink||minn==0) { return minn; } int r=0; for(int i=head[node];~i;i=edge[i].next) { int v=edge[i].to; if(dep[v]==dep[node]+1&&edge[i].capa>0) { int tmp=dfs(v,min(edge[i].capa,minn)); if(tmp>0) { edge[i].capa-=tmp; edge[i^1].capa+=tmp; r+=tmp; minn-=tmp; if(!minn) break; } } } if(!r) dep[node]=-1; return r; } int dinic() { int maxflow=0; while(bfs()) { maxflow+=dfs(source,inf); } return maxflow; } void build(int mid) { for(int i=1;i<=n;i++) { add(source,i,1); int len=vec[i].size(); for(int j=0;j<len;j++) { int x=vec[i][j]; add(i,n+x+1,1); } } for(int i=1;i<=m;i++) { add(n+i,sink,mid); } return; } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); while(~scanf("%d%d",&n,&m)) { getchar(); if(!n&&!m) break; source=0; sink=n+m+10; string str; int num; for(int i=1;i<=n;i++) { vec[i].clear(); getline(cin,str); stringstream stream(str); stream>>name; while(stream>>num) { vec[i].pb(num); } } int left=0; int right=n; while(left<=right) { int mid=(left+right)/2; init(); build(mid); int ans=dinic(); if(ans==n) { right=mid-1; } else { left=mid+1; } } printf("%d\n",left); } return 0; }