[hdu4292] Food [网络流]

题面:

传送门

思路:

又是一道网络流水题......

这道题一眼看来不难,就是一个食物和水的二分图

但是问题来了

怎么做到每个人只拿一份食物一份水呢?

显然每个人分配一个点是不够的

那我们就要使用拆点的技巧,把一个人拆成两个点,中间连一条容量为1的边,这两个点再分别和食物、水相连

食物和源点连,水连到汇点,然后源汇最大流就是答案了、

Code:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define inf 1e9
 6 using namespace std;
 7 inline int read(){
 8     int re=0,flag=1;char ch=getchar();
 9     while(ch>'9'||ch<'0'){
10         if(ch=='-') flag=-1;
11         ch=getchar();
12     }
13     while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
14     return re*flag;
15 }
16 int n,F,D,cnt,ans,first[1010],dep[1010],cur[1010];
17 struct edge{
18     int to,next,w;
19 }a[300010];
20 inline void add(int u,int v,int w){
21 //    cout<<"add "<<u<<ends<<v<<ends<<w<<endl;
22     a[++cnt]=(edge){v,first[u],w};first[u]=cnt;
23     a[++cnt]=(edge){u,first[v],0};first[v]=cnt;
24 }
25 void init(){
26     memset(first,-1,sizeof(first));memset(a,0,sizeof(a));
27     cnt=-1,ans=0;
28 }
29 bool bfs(int s,int t){
30     int q[1010],head=0,tail=1,i,u,v;
31     for(i=s;i<=t;i++) dep[i]=-1,cur[i]=first[i];
32     dep[s]=0;q[0]=s;
33     while(head<tail){
34         u=q[head++];
35         for(i=first[u];~i;i=a[i].next){
36             v=a[i].to;
37             if(~dep[v]||!a[i].w) continue;
38             dep[v]=dep[u]+1;q[tail++]=v;
39         }
40     }
41     return ~dep[t];
42 }
43 int dfs(int u,int t,int limit){
44     if(u==t||!limit) return limit;
45     int i,v,f,flow=0;
46     for(i=cur[u];~i;i=a[i].next){
47         cur[u]=i;v=a[i].to;
48         if(dep[v]==dep[u]+1&&(f=dfs(v,t,min(limit,a[i].w)))){
49             flow+=f;limit-=f;
50             a[i].w-=f;a[i^1].w+=f;
51             if(!limit) return flow;
52         }
53     }
54     return flow;
55 }
56 void dinic(int s,int t){
57     while(bfs(s,t)) ans+=dfs(s,t,inf);
58 }
59 int main(){
60     int i,j,t1;char s[210];
61     while(~scanf("%d%d%d",&n,&F,&D)){
62         init();
63         for(i=1;i<=n;i++) add(F+i,F+n+i,1);
64         for(i=1;i<=F;i++) t1=read(),add(0,i,t1);
65         for(i=1;i<=D;i++) t1=read(),add(F+n*2+i,F+D+n*2+1,t1);
66         for(i=1;i<=n;i++){
67             scanf("%s",s);
68             for(j=1;j<=F;j++){
69                 if(s[j-1]=='Y') add(j,F+i,inf);
70             }
71         }
72         for(i=1;i<=n;i++){
73             scanf("%s",s);
74             for(j=1;j<=D;j++){
75                 if(s[j-1]=='Y') add(F+n+i,F+n*2+j,inf);
76             }
77         }
78         dinic(0,F+D+n*2+1);
79         printf("%d
",ans);
80     }
81 }
原文地址:https://www.cnblogs.com/dedicatus545/p/8456578.html