Poj 3281 Dining

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\n",max_flow(s, t));
140     
141     return 0;
142 }

 

posted @ 2014-04-25 20:57  Der_Z  阅读(252)  评论(0编辑  收藏  举报