poj 1149 PIGS
建图题。
题意:1、M个猪圈,N个人来买猪,Mirko是农场主。
2、已知猪圈开始都上锁,Mirko不能动猪圈的猪。
3、客人依次来买猪,他们分别有A把猪圈的钥匙,从这些猪圈中买B头猪。
4、在每个客人走后,Mirko可以调整这些猪圈中猪的数量,来实现卖出更多的猪。然后锁上猪圈。
Hint:Sample中第一个人买完后,把猪圈1和猪圈2中的猪(2头)全部放到猪圈2中。
建图核心:如何判断哪些猪该调整 => 剩余猪的调整到将会再次被打开的猪圈
以顾客作为节点,超级源s连接没个猪圈的第一个顾客(如果某个顾客对多个猪圈来说是第一个购买,合并容量,e.g:Sample中,s与第一个人连一条容量为(3+1)=4的边),并记录下每个猪圈的最新买主,其余买家要和上一个买家连边,获得剩余的猪。
View Code
1 int main() 2 { 3 int n,m; 4 int st,ed; 5 int i,t,pos,x; 6 int p[M],vis[M][2],cus[N]; 7 while(scanf("%d%d",&m,&n)!=EOF) 8 { 9 st=n; 10 ed=st+1; 11 Init(); 12 memset(p,0,sizeof(p)); 13 memset(vis,0,sizeof(vis)); 14 memset(cus,0,sizeof(cus)); 15 for(i=1;i<=m;i++) 16 { 17 scanf("%d",&p[i]); 18 } 19 for(i=0;i<n;i++) 20 { 21 scanf("%d",&t); 22 while(t--) 23 { 24 scanf("%d",&pos); 25 vis[pos][0]++; 26 if(vis[pos][0]==1){ 27 cus[i]+=p[pos]; 28 vis[pos][1]=i; 29 }else { 30 Add(vis[pos][1],i,INF); 31 vis[pos][1]=i; 32 } 33 } 34 if(cus[i])Add(st,i,cus[i]); 35 scanf("%d",&x); 36 Add(i,ed,x); 37 } 38 printf("%d\n",Sap(st,ed,n+2)); 39 } 40 return 0; 41 }
以上是别人的思路。特点:简洁,形象。
本人没想出这么简洁的建图方法。晒晒自己的思路吧。
建图核心:既然要调整,那么就是我们不调整,直接从所有可调整的猪圈里买猪。Sample中:第一个顾客买了猪圈1和猪圈2的猪,然后顾客3来买猪圈2的猪,那么让顾客3与猪圈1、猪圈2连边 => 顾客3和顾客1连边。
M个猪圈+N个顾客=建立(M+N)个节点。超级源s与M个猪圈连边,容量就是猪圈的初始值。然后顾客买猪,连边方式就是按照输入,猪圈与顾客连边。顾客还要与之前和他在同一个猪圈买猪的顾客连边,最后每个顾客与超极汇t连边,容量就是顾客的购买量。
View Code
1 int main() 2 { 3 int i,j,k; 4 int x,num,pos; 5 while(scanf("%d%d",&m,&n)!=EOF) 6 { 7 int st=m+n+1; 8 int ed=st+1; 9 Init(); 10 for(i=1;i<=m;i++) 11 { 12 scanf("%d",&x); 13 Add(st,i,x); 14 } 15 for(i=1;i<=n;i++) 16 { 17 scanf("%d",&num); 18 for(j=0;j<num;j++) 19 { 20 scanf("%d",&pos); 21 Add(pos,m+i,INF); 22 for(int k=head[pos];k!=-1;k=e[k].next) 23 { 24 if(e[k].c)Add(e[k].v,m+i,INF); 25 } 26 } 27 scanf("%d",&x); 28 Add(m+i,ed,x); 29 } 30 printf("%d\n",Sap(st,ed,ed)); 31 } 32 return 0; 33 }