http://poj.org/problem?id=3281
题意:约翰给他的牛准备F种食物和D种饮料(约翰和牛,Alice和Bob……)每头牛都有自己喜欢的食物和饮料,而每种食物和饮料只能分配给一头牛。最多能有多少头牛能同时分配到喜欢的食物和饮料。
题解:最大流的模型之一,要用到所谓的拆点。除了牛、食物和饮料之外建立s和t,把牛的数量*2,两个分配相同的牛之间连边。连边顺序:s->食物->牛->牛->饮料->t。
注意:输入lf[][]、ld[][]时要注意t-1,因为题目数据是从1开始计数的。用小兰的话说:“好无赖啊……”。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cmath> 6 #include <string> 7 #include <vector> 8 #include <list> 9 #include <map> 10 #include <queue> 11 #include <stack> 12 #include <bitset> 13 #include <algorithm> 14 #include <numeric> 15 #include <functional> 16 #include <set> 17 #include <fstream> 18 19 using namespace std; 20 21 const int INF=100000000; 22 const int maxn=2100; 23 int lf[maxn][maxn],ld[maxn][maxn]; 24 struct edge{ 25 int to,cap,rev; 26 }; 27 vector<edge> G[maxn]; 28 int level[maxn]; 29 int iter[maxn]; 30 31 void add_edge(int from,int to,int cap) 32 { 33 G[from].push_back((edge){to,cap,(int)G[to].size()}); 34 G[to].push_back((edge){from,0,(int)G[from].size()-1}); 35 } 36 37 void bfs(int s) 38 { 39 memset(level, -1, sizeof(level)); 40 queue<int> que; 41 level[s]=0; 42 que.push(s); 43 while (!que.empty()) { 44 int v=que.front(); 45 que.pop(); 46 for (int i=0; i<G[v].size(); i++) { 47 edge &e=G[v][i]; 48 if (e.cap>0&&level[e.to]<0) { 49 level[e.to]=level[v]+1; 50 que.push(e.to); 51 } 52 } 53 } 54 } 55 56 int dfs(int v,int t,int f) 57 { 58 if (v==t) { 59 return f; 60 } 61 for (int &i=iter[v]; i<G[v].size(); i++) { 62 edge &e=G[v][i]; 63 if (e.cap>0 && level[v]<level[e.to]) { 64 int d=dfs(e.to, t, min(f,e.cap)); 65 if (d>0) { 66 e.cap-=d; 67 G[e.to][e.rev].cap+=d; 68 return d; 69 } 70 } 71 } 72 return 0; 73 } 74 75 int max_flow(int s,int t) 76 { 77 int flow=0; 78 for (;;) { 79 bfs(s); 80 if (level[t]<0) { 81 return flow; 82 } 83 memset(iter, 0, sizeof(iter)); 84 int f; 85 while ((f=dfs(s, t, INF))>0) { 86 flow+=f; 87 } 88 } 89 } 90 int main() 91 { 92 //freopen("/Users/apple/Desktop/poj 3281/poj 3281/in", "r", stdin); 93 //freopen("/Users/apple/Desktop/poj 3281/poj 3281/out", "w", stdout); 94 int N,F,D; 95 memset(lf, 0, sizeof(lf)); 96 memset(ld, 0, sizeof(ld)); 97 scanf("%d%d%d",&N,&F,&D); 98 int fi,di,fj,dk; 99 for (int i=0; i<N; i++) { 100 scanf("%d%d",&fi,&di); 101 for (int j=0; j<fi; j++) { 102 //scanf("%d",&lf[i][j]); 103 scanf("%d",&fj); 104 lf[i][fj-1]=1; 105 } 106 for (int k=0; k<di; k++) { 107 //scanf("%d",&ld[i][k]); 108 scanf("%d",&dk); 109 ld[i][dk-1]=1; 110 } 111 } 112 113 //0~N-1食物与牛 114 //N~N*2-1饮料与牛 115 //N*2~N*2+F-1食物 116 //N*2+F~N*2+F+D-1饮料 117 int s=N*2+F+D,t=s+1; 118 119 for (int i=0; i<F; i++) { 120 add_edge(s, N*2+i, 1); 121 } 122 for (int i=0; i<D; i++) { 123 add_edge(N*2+F+i, t, 1); 124 } 125 for (int i=0; i<N; i++) { 126 add_edge(i, N+i, 1); 127 for (int j=0; j<F; j++) { 128 if (lf[i][j]) { 129 add_edge(N*2+j, i, 1); 130 } 131 } 132 for (int k=0; k<D; k++) { 133 if (ld[i][k]) { 134 add_edge(N+i, N*2+F+k, 1); 135 } 136 } 137 } 138 139 printf("%d ",max_flow(s, t)); 140 141 return 0; 142 }