洛谷P1402 酒店之王
传送门:>Here<
题意:有N个人去酒店,酒店共有P个房间,Q道菜。已知每个人喜欢特定的几个房间和几道菜,一个人是满意的当且仅当住了喜欢的房间,吃了喜欢的菜(一个人只能选一个房间一道菜)。问最多有多少人是满意的
思路分析
利用最大流来解。这题看上去有点像二分图匹配,然而并不是“二分图”。显然只要我们建好图然后跑Dinic即可
如何建图呢?最初的一个想法是容量全部为1,每个人连向源点,再分别连向每道菜,再连向每个房间。然而一看样例跑出来就不对……
首先我们考虑到是人去选择,所以房间和菜肯定都是连人的,因此不能像刚才那样菜去连房间。
考虑把人放在中间,源点先连房间,房间连人,人连菜,菜再连到汇点
貌似没有什么问题?如果一共只有一个人,这个人喜欢三种菜和三种房间,那么按照这种做法答案会跑出来3。震惊,一个人竟然跑出来3!
其实问题就出在对最大流的理解上——最大流仅仅只有对管道容量的约束,并没有对每一个点能容纳多少有约束。在这道题里,一个人最多只能选择一个房间和一道菜,因此有必要把每一个人所能够得到的约束为1。这个其实也很好想,只需要把人拆开,每个人连一条容量为1的边到他的附身,这样即使前面的自己得到了多个匹配,经过后面的这一条管道也就只能流过1了,完美地解决了问题
Code
/*By DennyQi*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#define r read()
#define Max(a,b) (((a)>(b)) ? (a) : (b))
#define Min(a,b) (((a)<(b)) ? (a) : (b))
using namespace std;
typedef long long ll;
const int MAXN = ;
const int MAXM = ;
const int INF = ;
inline int read(){
int x = ; int w = ; register int c = getchar();
while(c ^ '-' && (c < '' || c > '')) c = getchar();
if(c == '-') w = -, c = getchar();
while(c >= '' && c <= '') x = (x << ) +(x << ) + c - '', c = getchar(); return x * w;
}
int N,P,Q,S,T,x;
int first[MAXM*],nxt[MAXM*],to[MAXM*],cap[MAXM*],flow[MAXM*],num_edge=-;
int level[MAXN],cur[MAXN];
queue <int> q;
inline void add(int u, int v, int c, int f){
to[++num_edge] = v;
cap[num_edge] = c;
flow[num_edge] = f;
nxt[num_edge] = first[u];
first[u] = num_edge;
}
inline bool BFS(){
memset(level, , sizeof(level));
while(!q.empty()) q.pop();
q.push(S);
level[S] = ;
int u,v;
while(!q.empty()){
u = q.front(); q.pop();
for(int i = first[u]; i != -; i = nxt[i]){
v = to[i];
if(!level[v] && cap[i]-flow[i] > ){
level[v] = level[u] + ;
q.push(v);
}
}
}
return level[T]!=;
}
int DFS(int u, int a){
if(u == T || a == ) return a;
int ans = ,v,_f;
for(int& i = cur[u]; i != -; i = nxt[i]){
v = to[i];
if(level[u]+==level[v] && cap[i]-flow[i] > ){
_f = DFS(v, Min(a, cap[i]-flow[i]));
ans += _f, a -= _f;
flow[i] += _f, flow[i^] -= _f;
if(a == ) break;
}
}
return ans;
}
inline void Dinic(){
int ans = ;
while(BFS()){
for(int i = S; i <= T; ++i) cur[i] = first[i];
ans += DFS(S, INF);
}
printf("%d", ans);
}
int main(){
N=r,P=r,Q=r;
S=, T = *N+P+Q+;
memset(first, -, sizeof(first));
for(int i = ; i <= P; ++i){
add(S, i+*N, , );
add(i+*N, S, , );
}
for(int i = ; i <= N; ++i){
for(int j = ; j <= P; ++j){
x=r;
if(x){
add(j+*N, i, , );
add(i, j+*N, , );
}
}
}
for(int i = ; i <= N; ++i){
add(i, i+N, , );
add(i+N, i, , );
}
for(int i = ; i <= N; ++i){
for(int j = ; j <= Q; ++j){
x=r;
if(x){
add(i+N, j+P+*N, , );
add(j+P+*N, i+N, , );
}
}
}
for(int i = ; i <= Q; ++i){
add(P+*N+i, T, , );
add(T, P+*N+i, , );
}
Dinic();
return ;
}
洛谷P1402 酒店之王的更多相关文章
- 洛谷P1402 酒店之王(二分图)
P1402 酒店之王 题目描述 XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化.由于很多来住店的旅客有自己喜好的房间色调.阳光等,也有自己所爱的菜,但是该酒店只有p间房间,一天只 ...
- 洛谷P1402 酒店之王(网络流)
### 洛谷P1402 题目链接 ### 题目大意:有 n 个人, p 间房间,q 种食物.每个人喜欢一些房间,一些食物,但每间房间.每种食物只能分配给一个人.问最大可以让多少个人满足(当且仅当分配到 ...
- 【刷题】洛谷 P1402 酒店之王
题目描述 XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化.由于很多来住店的旅客有自己喜好的房间色调.阳光等,也有自己所爱的菜,但是该酒店只有p间房间,一天只有固定的q道不同的菜. ...
- 洛谷 [P1402] 酒店之王
有两个约束条件的二分图匹配 我们回忆一下二分图匹配的匈牙利算法的具体流程,它是通过寻找增广路来判断最大匹配数的,我们再观察一下题目中的两个条件,只有两个条件都满足,才算找到一条增广路,所以我们可以分别 ...
- 2018.08.19 洛谷P1402 酒店之王(最大流)
传送门 最大流入门题,把人拆点即可. 代码: #include<bits/stdc++.h> #define N 505 using namespace std; inline int r ...
- 洛谷P2891 Dining P1402 酒店之王【类二分图匹配】题解+代码
洛谷P2891 Dining P1402 酒店之王[类二分图匹配]题解+代码 酒店之王 题目描述 XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化.由于很多来住店的旅客有自己喜好的 ...
- 「洛谷P1402」酒店之王 解题报告
P1402 酒店之王 题目描述 XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化.由于很多来住店的旅客有自己喜好的房间色调.阳光等,也有自己所爱的菜,但是该酒店只有p间房间,一天只 ...
- P1402 酒店之王
P1402 酒店之王 每个人要匹配一个A和一个B,所以这样连边: S向每个房间连边. 每个房间向喜欢这个房间的人连边. 每个人向喜欢的菜连边. 每道菜向T连边. 边权均为1. 注意人要限流. // I ...
- P1402 酒店之王【网络流】【最大流】
P1402 酒店之王 提交 5.39k 通过 2.16k 时间限制 1.00s 内存限制 125.00MB 题目提供者yeszy 难度省选/NOI- 历史分数100 提交记录 查看题解 标签 福建省历 ...
随机推荐
- JS判断当前设备类型
CSS3出来后,我们一般都是通过@media媒体查询来实现网页自适应,但是有时候,还是需要我们根据不同的设备来对应的做不同的显示,这时候,我们需要知道当前用户访问我们的界面用的是什么设备,怎么获取呢? ...
- Python_每日习题-0008-九九乘法表
题目: 输出9*9乘法口诀表. 程序分析:分行与分列的考虑,共9行9列,i控制行,j控制列. for i in range(1, 10): for j in range(1, i+1): print( ...
- 牛客国庆集训派对Day2
题目链接:https://www.nowcoder.com/acm/contest/202/A A 题意:给出最大4096*64和64*4096的矩阵,其中有一个矩阵只含有0和1,问你它们相乘所得到得 ...
- c++入门之引用
引用通常被用在函数形参传递的过程中.一般的参数传递的过程:将实参进行拷贝,函数中都是对拷贝的变量进行操作,而不是对原变量进行操作.但很多情况下,我们都希望对原变量进行操作.(比如交换两个变量的数值). ...
- iOS悬浮窗口(无论界面跳转、View始终在视图上显示,可移动)
2016.09.24 23:52* 字数 71 阅读 5925评论 9喜欢 11 让所有界面都显示,最好还是封装一个继承Window的类:JYCWindow. 先看看效果: mygif.gif 关 ...
- Telnet服务器和客户端请求处理
Telnet服务器和客户端请求处理 本文的控制台项目是根据SuperSocket官方Telnet示例代码进行调试的,官方示例代码:Telnet示例. 开始我的第一个Telnet控制台项目之旅: 创建控 ...
- 初次使用beego框架
安装beego框架以及bee工具 go get -u github.com/astaxie/beego go get github.com/beego/bee 创建一个新项目 bee new weba ...
- Tomcat v7.0 java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
十二月 , :: 下午 org.apache.coyote.http11.AbstractHttp11Processor process 信息: Error parsing HTTP request ...
- React Native之微信分享(iOS Android)
React Native之微信分享(iOS Android) 在使用React Native开发项目的时候,基本都会使用到微信好友或者微信朋友圈分享功能吧,那么今天我就带大家实现以下RN微信好友以及朋 ...
- 并发包 concurrent(一) Atomic
1:基础概念 悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁.传 ...