题目传送门:https://www.luogu.org/problem/P1402
题目描述
XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化。由于很多来住店的旅客有自己喜好的房间色调、阳光等,也有自己所爱的菜,但是该酒店只有p间房间,一天只有固定的q道不同的菜。
有一天来了n个客人,每个客人说出了自己喜欢哪些房间,喜欢哪道菜。但是很不幸,可能做不到让所有顾客满意(满意的条件是住进喜欢的房间,吃到喜欢的菜)。
这里要怎么分配,能使最多顾客满意呢?
输入格式
第一行给出三个正整数表示n,p,q(<=100)。
之后n行,每行p个数包含0或1,第i个数表示喜不喜欢第i个房间(1表示喜欢,0表示不喜欢)。
之后n行,每行q个数,表示喜不喜欢第i道菜。
输出格式
最大的顾客满意数。
输入输出样例
1 0
1 0
1 1
1 1
Solution:
~~本题一看就是网络流板子题嘛~~
一开始看到这题是,二话不说,先构图,超级源点连到房间,房间连接到人,人再连接到饭菜,最后饭菜再连接到超级汇点。结果一交上去,妈耶!WA了7个。看了一遍又一遍代码,就是找不到BUG。莫非,此题有坑?
随后点开了题解,才知道我是真的菜,网络流根本就没学好。各位用网络流的读者,请注意本题有一个巨坑,请看下这幅图读者就会明白了
一个人只能吃一道菜,住一间房嘛!!!(窝好菜,这么简单的问题都没考虑到QwQ)
然后,怎么处理呢?
其实,一人只吃一道菜,住一间房,本质上来说就是一个人只流过一次,我们不难想到,可以个每个人赋上一个流量,拆为两个点,这样没人就只流过一次啦!
如图:
到此,读者的思路应该也很清晰了,话不多说,上Code:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #include<queue> 7 #define R register 8 #define next kkksc03 9 using namespace std; 10 typedef long long ll; 11 typedef long double ld; 12 typedef unsigned long long ull; 13 inline ll read(); 14 ll n,p,q; 15 ll to[1000000],next[1000000],c[1000000],tot,head[1000000]; 16 inline void add(ll x,ll y,ll z){ 17 to[++tot]=y;c[tot]=z;next[tot]=head[x];head[x]=tot; 18 } 19 ll S,T; 20 ll d[1000000]; 21 queue<ll>Q; 22 bool bfs(){ 23 memset(d,0,sizeof d); 24 while(!Q.empty()) Q.pop(); 25 Q.push(S); 26 d[S]=1; 27 while(!Q.empty()){ 28 ll x=Q.front(); 29 Q.pop(); 30 for(R ll i=head[x];i;i=next[i]){ 31 ll ver=to[i]; 32 if(!d[ver]&&c[i]){ 33 d[ver]=d[x]+1; 34 Q.push(ver); 35 if(ver==T) return true; 36 } 37 } 38 } 39 return false; 40 } 41 ll dinic(ll x,ll flow){ 42 if(x==T||!flow) return flow; 43 ll k,rest=flow; 44 for(R ll i=head[x];i&&rest;i=next[i]){ 45 ll ver=to[i]; 46 if(d[ver]==d[x]+1&&c[i]){ 47 k=dinic(ver,min(rest,c[i])); 48 if(!k) d[ver]=0; 49 rest-=k; 50 c[i]-=k; 51 c[i^1]+=k; 52 } 53 } 54 return flow-rest; 55 } 56 int main(){ 57 n=read();p=read();q=read(); 58 S=0;T=n+n+p+q+1;tot=1; 59 for(R ll i=1;i<=n;i=-~i){ 60 for(R ll j=1,x;j<=p;j=-~j){ 61 x=read(); 62 if(!x) continue; 63 add(n+j,i,1); 64 add(i,n+j,0); 65 } 66 } 67 for(R ll i=1;i<=n;i=-~i){ 68 for(R ll j=1,x;j<=q;j=-~j){ 69 x=read(); 70 if(!x) continue; 71 add(i+p+q+n,n+p+j,1); 72 add(n+p+j,i+p+q+n,0); 73 } 74 } 75 for(R ll i=1;i<=p;i=-~i){ 76 add(S,n+i,1); 77 add(n+i,S,0); 78 } 79 for(R ll i=1;i<=n;i=-~i){ 80 add(i,n+p+q+i,1); 81 add(n+p+q+i,i,0); 82 } 83 for(R ll i=1;i<=q;i=-~i){ 84 add(n+p+i,T,1); 85 add(T,n+p+i,0); 86 } 87 ll _flow,maxflow=0; 88 while(bfs()){ 89 while(_flow=dinic(S,0x7fffffff)) maxflow+=_flow; 90 } 91 printf("%lld ",maxflow); 92 } 93 inline ll read(){ 94 ll x=0,t=1;char ch=getchar(); 95 while(ch<'0'||ch>'9'){ 96 if(ch=='-') t=-1; 97 ch=getchar(); 98 } 99 while(ch>='0'&&ch<='9'){ 100 x=(x<<1)+(x<<3)+(ch^48); 101 ch=getchar(); 102 } 103 return x*t; 104 }