题目链接:https://vjudge.net/problem/POJ-3281
题目:有不同种类的食物和饮料,每种只有1个库存,有N头牛,每头牛喜欢某些食物和某些饮料,但是一头牛
只能吃一种食物和喝一种饮料,问怎么分配食物和饮料才能让最多数量的牛饱餐。
思路:容易想到 食物->牛->饮料的流,当然一个牛可以被多个饮料流到,需要把牛拆成入点和出点,入点和出点流量为1,这样可以保证牛只吃或者喝某种食物和饮料,别的都流是套路,除了牛的分点之间流量为1,别的连接设置成1或者INF都一样,因为有牛的分点流量的限制。
1 #include2 #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 }