题目:http://acm.hdu.edu.cn/showproblem.php?pid=4292
题目意思:店里有N个顾客,F种食物和D种饮料,每个人都会有自己喜欢的食物和饮料,题目中对食物和饮料只有喜欢和不喜欢;店里每种食物和饮料的存货数量不同,顾客消费的标准是同时能分配他喜欢的食物和饮料,分配不到就走人。
在这样的限制下,求最多能分配多少人。
还是比较明显的最大流问题吧。
增加一个源点和一个汇点,源点到每种食物连一条边,容量为该种食物的数量;每种饮料到汇点连一条边,容量为该种饮料的数量。
然后对于每个人,他喜欢的食物就连一条容量1的边到人这里,人再连一条容量1的边到他喜欢的食物,但仅仅这样处理还不行,因为这样可能会使同一个人购买多种食物和饮料,所以还要多加一个限制,就是一个人只能购买1种食物和1种饮料,把1个人拆成两个点,左边用食物连进来,右边连到饮料,两个点之间再连一条容量1的边,这样就能保证每个人只购买1种饮料和1种食物。
然后剩下的就是套最大流算法的工作了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define N 1000
#define pb push_back
const int inf = 0x7fffffff;
struct Edge{
int from, to, cap, flow;
};
vector<Edge> G;
vector<int> V[N];
void add(int from, int to, int cap){
G.pb((Edge){from,to,cap,0});
G.pb((Edge){to,from,0,0});
int x=G.size();
V[from].pb(x-2);
V[to].pb(x-1);
}
int tar, d[N];
bool bfs(){
memset(d,-1,sizeof(d));
queue<int> Q;
Q.push(0);
d[0]=0;
while(!Q.empty()){
int x=Q.front(); Q.pop();
for(int i=0; i<V[x].size(); i++){
Edge& e = G[V[x][i]];
if(d[e.to]==-1 && e.cap>e.flow){
d[e.to] = d[x]+1;
Q.push(e.to);
}
}
}
return (d[tar]!=-1);
}
int cur[N];
int dfs(int u, int v){
if(u==tar || v==0) return v;
int flow=0, f;
for(int& i=cur[u]; i<V[u].size(); i++){
int j = V[u][i];
Edge& e = G[j];
if(d[e.to]==d[u]+1 && (f=dfs(e.to, min(v, e.cap-e.flow)))>0){
e.flow+=f;
flow+=f;
G[j^1].flow-=f;
v-=f;
if(v==0) break;
}
}
return flow;
}
int MaxFlow(){
int flow=0;
while(bfs()){
memset(cur,0,sizeof(cur));
flow+=dfs(0,inf);
}
return flow;
}
char s[1000];
int main(){
int n, f, d, v;
while(~scanf("%d %d %d", &n, &f, &d)){
tar = n+n+f+d+1;
for(int i=0; i<=tar; i++) V[i].clear();
G.clear();
for(int i=1; i<=f; i++){
scanf("%d", &v);
add(0, i, v);
}
for(int i=1; i<=d; i++){
scanf("%d", &v);
add(i+f, tar, v);
}
char ch;
for(int i=1; i<=n; i++){
for(int j=0; j<f; j++){
ch=getchar();
while(ch!='Y' && ch!='N') ch=getchar();
if(ch=='Y') add(j+1, i+f+d, 1);
}
}
for(int i=1; i<=n; i++){
for(int j=0; j<d; j++){
ch=getchar();
while(ch!='Y' && ch!='N') ch=getchar();
if(ch=='Y') add(i+f+d+n, j+1+f, 1);
}
}
for(int i=1; i<=n; i++){
add(i+f+d, i+f+d+n, 1);
}
printf("%d\n", MaxFlow());
}
return 0;
}