洛谷 P1402 酒店之王

 题目传送门: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
2 2 2
1 0
1 0
1 1
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\n",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 }

 

 

posted @ 2019-10-28 07:52  月落乌啼算钱  阅读(130)  评论(0编辑  收藏  举报