poj 1149 PIGS
有m个猪圈,每个猪圈上有若干头猪。有n个买猪的人,按顺序来买猪,每个人只会买固定几个猪圈里的猪,并且买猪有上限。当一个人买完猪后,他所买的那几个猪圈的猪可以互相走,问n个人依次买完,最多买多少头猪。
1<=m<=1000.1<=n<=100.
最大流。
裸的建图(每个人买猪的情况就建一层点)点数边数爆炸。
正解的建图是将猪圈间的转移放到买猪的人上,整张图只有n个点代表n个人。
源点到每个猪圈来买的第一个人连一条容量为该猪圈初始猪的数量的边。
对于每个猪圈,从第i个人来买的人向第i+1个来买的人连一条容量为正无穷的边。
每个人向汇点连一条容量为此人买猪上限的边。
最大流即为答案。
正无穷边实现流量传递,对于一个人买完离开时的情况,所有他能买的猪圈的流量都汇在他身上,由他连向下一个买的人,这就实现了猪圈间的流量传递。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 const int dian=105; 8 const int diann=1005; 9 const int bian=200005; 10 const int INF=0x3f3f3f3f; 11 int h[dian],nxt[bian],ver[bian],val[bian],ch[dian],cr[dian]; 12 int numm[diann],aa[diann][dian],rnum[diann],mnum[dian]; 13 int n,m,tot,a,b; 14 int S,T; 15 int add(int a,int b,int c){ 16 tot++;ver[tot]=b;val[tot]=c;nxt[tot]=h[a];h[a]=tot; 17 tot++;ver[tot]=a;val[tot]=0;nxt[tot]=h[b];h[b]=tot; 18 } 19 bool tell(){ 20 memset(ch,-1,sizeof(ch)); 21 queue<int>q; 22 q.push(S); 23 ch[S]=0; 24 while(!q.empty()){ 25 int t=q.front(); 26 q.pop(); 27 for(int i=h[t];i;i=nxt[i]) 28 if(ch[ver[i]]==-1&&val[i]){ 29 ch[ver[i]]=ch[t]+1; 30 q.push(ver[i]); 31 } 32 } 33 return ch[T]!=-1; 34 } 35 int zeng(int a,int b){ 36 if(a==T) 37 return b; 38 int r=0; 39 for(int i=cr[a];i&&b>r;i=nxt[i]) 40 if(ch[ver[i]]==ch[a]+1&&val[i]){ 41 int t=zeng(ver[i],min(b-r,val[i])); 42 val[i]-=t,r+=t,val[i^1]+=t; 43 if(val[i]) 44 cr[a]=i; 45 } 46 if(!r) 47 ch[a]=-1; 48 return r; 49 } 50 int dinic(){ 51 int r=0,t; 52 while(tell()){ 53 for(int i=1;i<=n+2;i++) 54 cr[i]=h[i]; 55 while(t=zeng(S,INF)) 56 r+=t; 57 } 58 return r; 59 } 60 int main(){ 61 memset(h,0,sizeof(h)); 62 memset(nxt,0,sizeof(nxt)); 63 memset(rnum,0,sizeof(rnum)); 64 tot=1; 65 scanf("%d%d",&m,&n); 66 S=n+1,T=n+2; 67 for(int i=1;i<=m;i++) 68 scanf("%d",&numm[i]); 69 for(int i=1;i<=n;i++){ 70 scanf("%d",&a); 71 for(int j=1;j<=a;j++){ 72 scanf("%d",&b); 73 rnum[b]++; 74 aa[b][rnum[b]]=i; 75 } 76 scanf("%d",&a); 77 mnum[i]=a; 78 } 79 for(int i=1;i<=m;i++){ 80 add(S,aa[i][1],numm[i]); 81 for(int j=1;j<rnum[i];j++) 82 add(aa[i][j],aa[i][j+1],INF); 83 } 84 for(int i=1;i<=n;i++) 85 add(i,T,mnum[i]); 86 printf("%d",dinic()); 87 return 0; 88 }