POJ--3281(最大流,拆点)
2014-12-20 18:05:00
思路:嘛,这题终于不是max-flow果题了。
因为种种限制,需要将牛进行拆点,从而限制每头牛只能选择一种dish和一种drink,每头牛拆为两点,点间建边,容量为1。
(我本来是将dish拆点的,怎么想都觉得对,后来发现如果按照牛 -> dish_in -> dish_out -> drink这样建图的话,为使得dish_out和drink之间的边不具有牛的编号性,即各条边不知道是哪个牛的选择,可能有些牛不喜欢某种搭配,但因为其他牛喜欢这种搭配而强行被当成一条通路了,自然就WA了)
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <iostream> 11 #include <algorithm> 12 using namespace std; 13 #define lp (p << 1) 14 #define rp (p << 1|1) 15 #define getmid(l,r) (l + (r - l) / 2) 16 #define MP(a,b) make_pair(a,b) 17 typedef long long ll; 18 typedef unsigned long long ull; 19 const int INF = 1 << 30; 20 const int maxn = 1000; 21 22 int N,F,D; 23 int cp[maxn][maxn],ed,lev[maxn]; 24 int Q[maxn],head,rear; 25 26 void Bfs(){ 27 memset(lev,-1,sizeof(lev)); 28 Q[head = rear = 1] = 0; 29 lev[0] = 0; 30 while(head <= rear){ 31 int x = Q[head++]; 32 for(int i = 1; i <= ed; ++i) if(lev[i] < 0 && cp[x][i] > 0){ 33 lev[i] = lev[x] + 1; 34 Q[++rear] = i; 35 } 36 } 37 } 38 39 int Dfs(int p,int minf){ 40 if(p == ed) return minf; 41 for(int i = 1; i <= ed; ++i) if(lev[i] > lev[p] && cp[p][i] > 0){ 42 int d = Dfs(i,min(cp[p][i],minf)); 43 if(d > 0){ 44 cp[p][i] -= d; 45 cp[i][p] += d; 46 return d; 47 } 48 } 49 return 0; 50 } 51 52 int Dinic(){ 53 int max_flow = 0,plus; 54 while(1){ 55 Bfs(); 56 if(lev[ed] < 0) break; 57 while((plus = Dfs(0,INF)) > 0) max_flow += plus; 58 } 59 return max_flow; 60 } 61 62 int main(){ 63 memset(cp,0,sizeof(cp)); 64 int a,b,c,tmp[maxn]; 65 scanf("%d%d%d",&N,&F,&D); 66 ed = F + N + N + D + 1; 67 for(int i = 1; i <= F; ++i) cp[0][i] = 1; //source to food 68 for(int i = 1; i <= N; ++i) cp[F + i][F + N + i] = 1; //cows-in to cows-out 69 for(int i = 1; i <= D; ++i) cp[F + N + N + i][ed] = 1; //drinks to ed 70 for(int i = 1; i <= N; ++i){ //food to cows-in and cows-out to drinks 71 scanf("%d%d",&a,&b); 72 for(int j = 1; j <= a; ++j){ 73 scanf("%d",&c); 74 cp[c][F + i] = 1; 75 } 76 for(int j = 1; j <= b; ++j){ 77 scanf("%d",&c); 78 cp[F + N + i][F + N + N + c] = 1; 79 } 80 } 81 printf("%d\n",Dinic()); 82 return 0; 83 }