POJ2289,最大流,二分
阿新 • • 發佈:2018-12-13
題目連結:Jamie’s Contact Groups 建圖: 從源點向i連邊,容量為1;i向i’連邊,容量為1;i’向可以放置的代號連邊,容量為1,;0-m個容器向匯點連邊,容量待定。 用二分法判斷,在該容量下,最大流是否為n,是則可以,否則不可。 程式碼如下:
/************************************************************************* > File Name: main.cpp > Author:Eagles > Mail:None > Created Time: 2018年10月05日 星期五 10時32分20秒 > Description:POJ2289 ************************************************************************/ #include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<vector> #include<stack> #include<bitset> #include<cstdlib> #include<set> #include<list> #include<deque> #include<map> #include<queue> using namespace std; #define N 20000 struct node { int to; int val; int nex; }E[N*100]; int head[N],lev[N]; int n,m,S,T,cnt; const int inf=10000000; char name[2000]; int info[N][N]; void addEdge(int a,int b, int val) { E[cnt].to=b; E[cnt].val=val; E[cnt].nex=head[a]; head[a]=cnt++; E[cnt].to=a; E[cnt].val=0; E[cnt].nex=head[b]; head[b]=cnt++; } bool bfs() { memset(lev,0,sizeof(lev)); queue<int>q; q.push(S); lev[S]=1; while (!q.empty()) { int u=q.front(); q.pop(); for (int i=head[u]; i!=-1; i=E[i].nex) { int v=E[i].to; if (E[i].val >0&&lev[v]==0) { lev[v]=lev[u]+1; q.push(v); if (v == T) return true; } } } return false; } int dfs(int u, int f) { if (u==T) return f; int tag=0; for (int i=head[u]; i!=-1; i=E[i].nex) { int v=E[i].to; if (E[i].val>0&&lev[v]==lev[u]+1) { int d=dfs(v,min(f-tag,E[i].val)); E[i].val-=d; E[i^1].val+=d; tag+=d; if (tag==f) return f; } } return tag; } int Dinic() { int ans=0; while (bfs()) { ans+=dfs(S,inf); } return ans; } void read_in() { getchar(); for (int i=0; i<n; i++) { scanf("%s",name); int the_size=0; int x; char a; while (1) { scanf("%d",&x); info[i][++the_size]=x; a=getchar(); if (a=='\n') break; } info[i][0]=the_size; } } void init(int mid) { memset(head,-1,sizeof(head)); cnt=0; S=2*n+m; T=2*n+m+1; for (int i=0; i<n; i++) { int left=2*i; int right=2*i+1; addEdge(S,left,1); addEdge(left,right,1); for (int j=1; j<=info[i][0]; j++) { addEdge(right,info[i][j]+2*n,inf); } } for (int i=0; i<m; i++) addEdge(2*n+i,T,mid); } bool check(int mid) { init(mid); int ans=Dinic(); return ans==n; } int main() { while (~scanf("%d%d",&n,&m)&&(m+n)) { read_in(); int l=1,r=n; int mid,ans; while (l+1<r) { mid=(l+r)>>1; if (check(mid)) r=mid; else l=mid+1; } if (check(l)) r=l; printf("%d\n",r); } return 0; }