kuangbin专题专题十一 网络流 Dining POJ - 3281

题目链接:https://vjudge.net/problem/POJ-3281

题目:有不同种类的食物和饮料,每种只有1个库存,有N头牛,每头牛喜欢某些食物和某些饮料,但是一头牛

只能吃一种食物和喝一种饮料,问怎么分配食物和饮料才能让最多数量的牛饱餐。

 

思路:容易想到  食物->牛->饮料的流,当然一个牛可以被多个饮料流到,需要把牛拆成入点和出点,入点和出点流量为1,这样可以保证牛只吃或者喝某种食物和饮料,别的都流是套路,除了牛的分点之间流量为1,别的连接设置成1或者INF都一样,因为有牛的分点流量的限制。

  1 #include 
  2 #include 
  3 #include 
  4 #include 
  5 using namespace std;
  6 
  7 const int N = 410,INF = (int)1e9;
  8 int n,F,D,tot,S,T;
  9 int head[N],lev[N];
 10 queue<int > que;
 11 struct node{
 12     int to,nxt,flow;
 13 }e[N*N];
 14 
 15 inline void add(int u,int v,int flow){
 16     e[tot].to = v;
 17     e[tot].flow = flow;
 18     e[tot].nxt = head[u];
 19     head[u] = tot++;
 20     e[tot].to = u;
 21     e[tot].flow = 0;
 22     e[tot].nxt = head[v];
 23     head[v] = tot++;
 24 }
 25 
 26 void build_map(int s,int t){
 27 
 28     for(int i = s; i <= t; ++i) head[i] = -1; tot = 0;
 29     //读入信息  0是源点 1~F食物 F+1~F+2*n牛 F+2*n+1~F+2*n+D饮料 F+2*n+D+1是汇点
 30     int kind_f,kind_d,x;
 31     for(int i = 1; i <= n; ++i){
 32         scanf("%d%d",&kind_f,&kind_d);
 33         for(int j = 1; j <= kind_f; ++j){
 34             scanf("%d",&x);
 35             add(x,F+i,1);// add(F+i,x,0);
 36         }
 37         for(int j = 1; j <= kind_d; ++j){
 38             scanf("%d",&x);
 39             add(F+n+i,F+2*n+x,1);// add(F+2*n+x,F+n+i,0);
 40         }
 41     }
 42     for(int i = 1; i <= F; ++i){
 43         add(s,i,1);// add(i,s,0);
 44     }
 45     for(int i = 1; i <= D; ++i){
 46         add(F+2*n+i,t,1);// add(t,F+2*n+i,0);
 47     }
 48     for(int i = 1; i <= n; ++i){
 49         add(F+i,F+n+i,1);// add(F+n+i,F+i,0);
 50     }
 51 }
 52 
 53 void show(int s,int t){
 54     for(int i = s; i <= t; ++i){
 55         cout << "当前点为 " << i << "    ";
 56         cout << "能去到 ";
 57         for(int o = head[i]; ~o; o = e[o].nxt){
 58             printf("  %d 流量为 %d",e[o].to,e[o].flow);
 59         }cout << endl;
 60     }
 61 }
 62 
 63 bool bfs(int s,int t){
 64     while(!que.empty()) que.pop();
 65     for(int i = s; i <= t; ++i) lev[i] = 0;
 66     lev[s] = 1;
 67     que.push(s);
 68     while(!que.empty()){
 69         int u = que.front(); que.pop();
 70         for(int o = head[u]; ~o; o = e[o].nxt){
 71             int v = e[o].to;
 72             if(!lev[v] && e[o].flow ){
 73                 lev[v] = lev[u] + 1;
 74                 if(v == t) return true;
 75                 que.push(v);
 76             }
 77         }
 78     }
 79     return false;
 80 }
 81 
 82 int dfs(int now,int flow,int t){
 83     if(now == t) return flow;
 84     int to,sum = 0,tmp;
 85     for(int o = head[now]; ~o; o = e[o].nxt){
 86         to = e[o].to;
 87         if((lev[to] == lev[now] + 1) && e[o].flow && (tmp = dfs(to,min(flow-sum,e[o].flow),t))){
 88             e[o].flow -= tmp;
 89             e[o^1].flow += tmp;
 90             if((sum += tmp) == flow) return sum;
 91         }
 92     }
 93     return sum;
 94 }
 95 
 96 int mf(int s,int t){
 97     int _mf = 0;
 98     while(bfs(s,t)){
 99         _mf += dfs(s,INF,t);
100     }
101     return _mf;
102 }
103 
104 int main(){
105 
106     scanf("%d%d%d",&n,&F,&D);
107     S = 0; T = F+2*n+D+1;
108     //建图
109     build_map(S,T);
110    // show(S,T); //图的显示
111     int ans = mf(S,T);
112     printf("%d\n",ans);
113 
114     return 0;
115 }

 

你可能感兴趣的:(kuangbin专题专题十一 网络流 Dining POJ - 3281)