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 }

 

 

posted @ 2013-04-30 17:44  Thousand Sunny  阅读(224)  评论(0编辑  收藏  举报