HDU 4292 网络源 Food
HDU 4292 网络流 Food
题意:
n 个人 f 种食物 d 种饮料
f 个数字表示每种食物的个数
d个数字表示每种饮料的个数
n行f列
i行j列表示 第i个人是否喜欢 第j 种食物
n行d列
同上
当一个人同时有吃有喝就被满足,问最多能满足多少人
思路:
设0为源点
[1, f ] 表示食物 (若i行j列是 Y 则建边 addedge(i, f+j , 1) )
把人拆点拆成 i 和 i+n 边权为1
[f +1, f + n] 和 [ f + n +1, f + n +n ] 表示人
[ f+n+n +i, f+n+n + d]表示各种饮料,与 人建边如上
再把饮料连到汇点
则最大流就是最大人数
#include <stdio.h> #include <string.h> #include <queue> using namespace std; #define N 90000 #define inf 536870912 inline int Max(int a,int b){return a<b?b:a;} inline int Min(int a,int b){return a>b?b:a;} struct Edge{ int from, to, cap, nex; }edge[N*10]; int head[N], edgenum; void addedge(int u, int v, int cap){ Edge E = { u, v, cap, head[u]}; edge[ edgenum ] = E; head[u] = edgenum ++; Edge E1= { v, u, 0, head[v]}; edge[ edgenum ] = E1; head[v] = edgenum ++; } int sign[N], s, t; bool BFS(int from, int to){ memset(sign, -1, sizeof(sign)); sign[from] = 0; queue<int>q; q.push(from); while( !q.empty() ){ int u = q.front(); q.pop(); for(int i = head[u]; i!=-1; i = edge[i].nex) { int v = edge[i].to; if(sign[v]==-1 && edge[i].cap) { sign[v] = sign[u] + 1, q.push(v); if(sign[to] != -1)return true; } } } return false; } int Stack[N], top, cur[N]; int dinic(){ int ans = 0; while( BFS(s, t) ) { memcpy(cur, head, sizeof(head)); int u = s; top = 0; while(1) { if(u == t) { int flow = inf, loc;//loc 表示 Stack 中 cap 最小的边 for(int i = 0; i < top; i++) if(flow > edge[ Stack[i] ].cap) { flow = edge[Stack[i]].cap; loc = i; } for(int i = 0; i < top; i++) { edge[ Stack[i] ].cap -= flow; edge[Stack[i]^1].cap += flow; } ans += flow; top = loc; u = edge[Stack[top]].from; } for(int i = cur[u]; i!=-1; cur[u] = i = edge[i].nex)//cur[u] 表示u所在能增广的边的下标 if(edge[i].cap && (sign[u] + 1 == sign[ edge[i].to ]))break; if(cur[u] != -1) { Stack[top++] = cur[u]; u = edge[ cur[u] ].to; } else { if( top == 0 )break; sign[u] = -1; u = edge[ Stack[--top] ].from; } } } return ans; } int flow; char hehe[300]; int main(){ int n,f,d; int i, j; while(~scanf("%d %d %d",&n,&f,&d)){ memset(head,-1,sizeof(head)); edgenum = 0; s = 0, t = f + 2*n + d + 1; for(i = 1;i <= f; i++) { scanf("%d",&flow); addedge(s, i, flow); } for(i = 1;i <= d; i++) { scanf("%d",&flow); addedge(f+2*n+i, t, flow); } for(i = 1;i <= n; i++) { scanf("%s",hehe+1); for(j = 1; j <= f; j++) if(hehe[j] == 'Y') { addedge(j, f+i, 1); } } for(i = 1;i <= n; i++) { scanf("%s",hehe+1); for(j = 1; j <= d; j++) if(hehe[j] == 'Y') { addedge(f+n+i, f+2*n+j, 1); } } for(i = 1;i <= n; i++) addedge(f+i, f+n+i, 1); printf("%d\n",dinic()); } return 0; } /* 4 3 3 1 1 1 1 1 1 YYN NYY YNY YNY YNY YYN YYN NNY 2 1 1 10 10 Y N Y N 2 1 2 10 1 2 Y Y YN NN */