poj 3281 Dining (最大网络流)

题目链接:

  http://poj.org/problem?id=3281

题目大意:

  有n头牛,f种食物,d种饮料,第i头牛喜欢fi种食物和di种饮料,每种食物或者饮料被一头牛选中后,就不能被其他的牛选了,问最多能满足多少头牛的要求?

解题思路:

  最大匹配问题,关键在于如何建图,可以虚构出来一个源点,一个汇点,一共需要f+d+2*n+2个点即可,建图为:源点—>食物—>牛—>牛—>饮料—> 汇点。把牛作为点拆开建图是为了让一头牛只对应一种饮料和一种食物,避免出现对应多种饮料或者多种食物的情况。

代码:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <algorithm>
  5 #include <iostream>
  6 #include <cmath>
  7 #include <queue>
  8 using namespace std;
  9 
 10 #define maxn 0x3f3f3f3f
 11 #define N 410
 12 int map[N][N], Layer[N], s, e;
 13 bool visit[N];
 14 bool CountLayer();
 15 int Dinic ();
 16 
 17 int main ()
 18 {
 19     int n, f, d, x, y, m;
 20     while (scanf ("%d %d %d", &n, &f, &d) != EOF)
 21     {
 22         s = 0, e = f + d + n + n + 1;
 23         memset (map, 0, sizeof(map));
 24 
 25         for (int i=1; i<=f; i++)
 26             map[0][i] = 1;//食物和源点连线
 27 
 28         for (int i=1; i<=d; i++)
 29             map[i+f+2*n][e] = 1;//饮料和汇点链接
 30 
 31         for (int i=1; i<=n; i++)
 32             map[i+f][i+f+n] = 1;//对应的牛和牛链接
 33 
 34         for (int i=1; i<=n; i++)
 35         {//建立牛和食物及饮料的关系
 36             int num = f + i;
 37             scanf ("%d %d", &x, &y);
 38             while (x --)
 39             {
 40                 scanf ("%d", &m);
 41                 map[m][num] = 1;
 42             }
 43             while (y --)
 44             {
 45                 scanf ("%d", &m);
 46                 map[num + n][m+f+2*n] = 1;
 47             }
 48         }
 49         printf ("%d\n", Dinic());
 50     }
 51     return 0;
 52 }
 53 
 54 bool CountLayer()
 55 {
 56     deque <int> Q;
 57     memset (Layer, 0, sizeof(Layer));
 58     Layer[0] = 1;
 59     Q.push_back(0);
 60     while (!Q.empty())
 61     {
 62         int nd = Q.front();
 63         Q.pop_front();
 64         for (int i=s; i<=e; i++)
 65         {
 66             if (map[nd][i]>0 && !Layer[i])
 67             {
 68                 Layer[i] = Layer[nd] + 1;
 69                 if (i == e)
 70                     return true;
 71                 else
 72                     Q.push_back(i);
 73             }
 74         }
 75     }
 76     return false;
 77 }
 78 
 79 int Dinic ()//Dinic模板
 80 {
 81     int maxnflow = 0, i;
 82     while (CountLayer())
 83     {
 84         deque<int>Q;
 85         memset (visit, 0, sizeof(visit));
 86         visit[0] = 1;
 87         Q.push_back(0);
 88         while (!Q.empty())
 89         {
 90             int nd = Q.back();
 91             if (nd != e)
 92             {
 93                 for (i=0; i<=e; i++)
 94                 {
 95                     if (map[nd][i]>0 && Layer[i] == Layer[nd]+1 && !visit[i])
 96                     {
 97                         visit[i] = 1;
 98                         Q.push_back(i);
 99                         break;
100                     }
101                 }
102                 if (i > e)
103                     Q.pop_back();
104             }
105             else
106             {
107                 int minflow = maxn;
108                 int mv;
109                 for (i=1; i<Q.size(); i++)
110                 {
111                     int ns = Q[i-1];
112                     int ne = Q[i];
113                     if (map[ns][ne] < minflow)
114                     {
115                         minflow = map[ns][ne];
116                         mv = ns;
117                     }
118                 }
119                 maxnflow += minflow;
120                 for (i=1; i<Q.size(); i++)
121                 {
122                     int ns = Q[i-1];
123                     int ne = Q[i];
124                     map[ns][ne] -= minflow;
125                     map[ne][ns] += minflow;
126                 }
127                 while (!Q.empty() && Q.back() != mv)
128                     Q.pop_back();
129             }
130         }
131     }
132     return maxnflow;
133 }

 

你可能感兴趣的:(poj)