题目链接:
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 }
时间: 2024-10-03 13:49:57