poj3281_网络流_EK算法

题意:分配问题,有F种食物,D种饮料,N头牛,每头牛有自己喜欢的吃的和喝的东西,现在让你去分配,使得吃喝都得到的牛最多。每种吃喝的东西只能招待一头牛。

分析:把一头牛拆成两头,一头和食物连,一头和饮料连,当然这两头牛之间肯定要连一条边,添加一个源点汇点分别向食物和饮料连。这里把牛拆成两个点是为了限制进过牛的流最大为1,这样就可以通过求最大流来得到答案。

举例说明为什么要拆牛:(见discuss)

比如只有1条牛,1 2 两种食物,1 2两种水

那图会是下边那样的

食物1                食物2
  |                    |
  |                    |
   -----> 牛 <----
             / \
            /   \
  水1<--|    |----> 水2

对应的输入数据是
1 2 2
2 2 1 2 1 2
这时候答案为2了WA了,因为没有拆点,所以导致一头牛享受了两套美餐,这怎么可以呢
而拆成下边那样就对了
食物1            食物2
  |                 |
  |                 |
   --> 牛1<---
           /
         /
         \
          |-->还是牛1
               / \
              /   \
    水1<--|    |-----> 水2

至于要拆牛,而不是拆食物的原因:因为一头牛只能选一种食物和饮料,把牛拆了,中间的容量为1.这样可以保证它只选一种。如果不拆牛的话不能保证。

刚学习了EK算法,这个题用的是邻接矩阵的EK算法。

代码:

 

View Code
  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <memory.h>
  4 #include <queue>
  5 using namespace std;
  6 const int maxdata=(1<<30);  //!!!
  7 const int maxnum=405;
  8 int f[maxnum][maxnum];
  9 int pre[maxnum];
 10 int cf[maxnum];
 11 int food,d,n;
 12 queue<int> q;
 13 
 14 void Init()
 15 {
 16     int i,j;
 17     memset(f,0,sizeof(f));
 18     scanf("%d%d%d",&n,&food,&d);
 19 
 20     for(i=1;i<=food;i++)
 21         f[0][i]=1;
 22     for(i=1;i<=n;i++)
 23         f[i+food][i+food+n]=1;
 24     for(i=1;i<=d;i++)
 25         f[i+food+n+n][food+n+n+d+1]=1;
 26 
 27 
 28     int fnum,dnum,ftemp,dtemp;
 29     for(i=1;i<=n;i++)
 30     {
 31         scanf("%d%d",&fnum,&dnum);
 32         for(j=1;j<=fnum;j++)
 33         {
 34             scanf("%d",&ftemp);
 35             f[ftemp][i+food]=1;
 36         }
 37         for(j=1;j<=dnum;j++)
 38         {
 39             scanf("%d",&dtemp);
 40             f[i+food+n][food+n+n+dtemp]=1;
 41         }
 42     }
 43 }
 44 
 45 int bfs(int s,int e)
 46 {
 47     int i,t;
 48     while(!q.empty())
 49         q.pop();
 50     for(i=s;i<=e;i++)
 51         pre[i]=-1;
 52 
 53     cf[s]=maxdata;
 54     q.push(s);
 55     while(!q.empty())
 56     {
 57         t=q.front();
 58         q.pop();
 59         if(t==e)   //!!!
 60             break;
 61         for(i=s;i<=e;i++)
 62         {
 63             if(i!=t && f[t][i]>0 && pre[i]==-1)
 64             {
 65                 pre[i]=t;
 66                 cf[i]=min(f[t][i],cf[t]);
 67                 q.push(i);
 68             }
 69         }
 70     }
 71     if(pre[e]==-1)
 72         return -1;
 73     return cf[e];
 74 }
 75 
 76 int Maxflow(int s,int e)
 77 {
 78     int p,q;
 79     int ans=0;
 80     int sum=0;
 81     while(1)
 82     {
 83         ans=bfs(s,e);
 84         if(ans==-1)
 85             break;
 86         q=e;
 87         while(q!=s)
 88         {
 89             p=pre[q];
 90             f[p][q]-=ans;
 91             f[q][p]+=ans;
 92             q=p;
 93         }
 94         sum+=ans;
 95     }
 96     return sum;
 97 }
 98 
 99 int main()
100 {
101     Init();
102     printf("%d\n",Maxflow(0,food+n+n+d+1));
103     return 0;
104 }
105 
106 /*
107 4 3 3
108 2 2 1 2 1 3
109 2 2 2 3 1 2
110 2 2 1 3 1 2
111 2 1 1 3 3
112 */

tjuoj 2823

 

posted @ 2012-08-11 20:21  pushing my way  阅读(328)  评论(0编辑  收藏  举报