题目链接
https://vjudge.net/problem/HDU-4292
题意
n个人,f食物,d饮品,每个人要么不吃不喝,要么有吃有喝,给定食物饮品数量,每个人对食物饮品的偏好,求最大满足多少人
思路
和前两天写的那个牛的那题一个思路,只不过因为食物饮料有数量,边权把1换成数量就行了。建图比较简单,写在代码注释里了,如果还是有点不懂可以看我这篇博客POJ - 3281
代码
#include<cstdio>
#include<iostream>
#include<iomanip>
#include<map>
#include<string>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
//#define int long long
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=1010;//200food + 200drink + 200*2people + s + t
const int maxe=200010;//(200+200*200+200+200*200+200)*2
int head[maxn],cnt;
struct Edge{
int v;
int w;
int next;
}edge[maxe];
int n,f,d,s,t;
ll maxflow;
int deep[maxn];
int now[maxe];
void init(){
memset(head,-1,sizeof(head));
cnt=0;
maxflow=0;
return ;
}
void add(int u,int v,int w){
//cout<<u<<" "<<v<<" "<<w<<endl;
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
}
inline bool bfs(){
memset(deep,0x3f,sizeof(deep));
queue<int>q;
q.push(s);deep[s] = 0;now[s] = head[s];
while(q.size()){
int x = q.front();q.pop();
for(int i=head[x];i!=-1;i=edge[i].next){
int y=edge[i].v;
if(edge[i].w>0&&deep[y]==inf){
q.push(y);
now[y]=head[y];
deep[y]=deep[x]+1;
if(y==t) return 1;
}
}
}
return 0;
}
ll dfs(int x,int flow){
if(x==t) return flow;
ll ans = 0,k,i;
for(i=now[x];i!=-1&&flow;i=edge[i].next){
now[x]=i;
int y=edge[i].v;
if(edge[i].w>0&&(deep[y]==deep[x]+1)){
k=dfs(y,min(flow,edge[i].w));
if(!k) deep[y]=inf;
edge[i].w-=k;
edge[i^1].w+=k;
ans+=k;
flow-=k;
}
}
return ans;
}
void dinic(){
while(bfs())
maxflow+=dfs(s,inf);
}
int main(){
IOS
//一定注意多组输入
while(cin>>n>>f>>d){
//s,t设成绝对标不到的两个数
s=999,t=s+1;
init();
//编号方便
int _fd=0,_dk=205,_pl=410,_pll=615;
//s向食物连边,权为数量
for(int i=1;i<=f;i++){
int ff;
cin>>ff;
add(s,i+_fd,ff);
add(i+_fd,s,0);
}
//饮料向t连边,权为数量
for(int i=1;i<=d;i++){
int dd;
cin>>dd;
add(i+_dk,t,dd);
add(t,i+_dk,0);
}
//食物向人in连边,权1
for(int i=1;i<=n;i++){
char ch;
for(int j=1;j<=f;j++){
cin>>ch;
if(ch=='Y'){
add(j+_fd,i+_pl,1);
add(i+_pl,j+_fd,0);
}
}
}
//人out向饮料连边,权1
for(int i=1;i<=n;i++){
char ch;
for(int j=1;j<=d;j++){
cin>>ch;
if(ch=='Y'){
add(i+_pll,j+_dk,1);
add(j+_dk,i+_pll,0);
}
}
}
//人in向人out连边,权1
for(int i=1;i<=n;i++){
add(i+_pl,i+_pll,1);
add(i+_pll,i+_pl,0);
}
dinic();
cout<<maxflow<<endl;
}
return 0;
}