传送门:>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 酒店之王的更多相关文章

  1. 洛谷P1402 酒店之王(二分图)

    P1402 酒店之王 题目描述 XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化.由于很多来住店的旅客有自己喜好的房间色调.阳光等,也有自己所爱的菜,但是该酒店只有p间房间,一天只 ...

  2. 洛谷P1402 酒店之王(网络流)

    ### 洛谷P1402 题目链接 ### 题目大意:有 n 个人, p 间房间,q 种食物.每个人喜欢一些房间,一些食物,但每间房间.每种食物只能分配给一个人.问最大可以让多少个人满足(当且仅当分配到 ...

  3. 【刷题】洛谷 P1402 酒店之王

    题目描述 XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化.由于很多来住店的旅客有自己喜好的房间色调.阳光等,也有自己所爱的菜,但是该酒店只有p间房间,一天只有固定的q道不同的菜. ...

  4. 洛谷 [P1402] 酒店之王

    有两个约束条件的二分图匹配 我们回忆一下二分图匹配的匈牙利算法的具体流程,它是通过寻找增广路来判断最大匹配数的,我们再观察一下题目中的两个条件,只有两个条件都满足,才算找到一条增广路,所以我们可以分别 ...

  5. 2018.08.19 洛谷P1402 酒店之王(最大流)

    传送门 最大流入门题,把人拆点即可. 代码: #include<bits/stdc++.h> #define N 505 using namespace std; inline int r ...

  6. 洛谷P2891 Dining P1402 酒店之王【类二分图匹配】题解+代码

    洛谷P2891 Dining P1402 酒店之王[类二分图匹配]题解+代码 酒店之王 题目描述 XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化.由于很多来住店的旅客有自己喜好的 ...

  7. 「洛谷P1402」酒店之王 解题报告

    P1402 酒店之王 题目描述 XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化.由于很多来住店的旅客有自己喜好的房间色调.阳光等,也有自己所爱的菜,但是该酒店只有p间房间,一天只 ...

  8. P1402 酒店之王

    P1402 酒店之王 每个人要匹配一个A和一个B,所以这样连边: S向每个房间连边. 每个房间向喜欢这个房间的人连边. 每个人向喜欢的菜连边. 每道菜向T连边. 边权均为1. 注意人要限流. // I ...

  9. P1402 酒店之王【网络流】【最大流】

    P1402 酒店之王 提交 5.39k 通过 2.16k 时间限制 1.00s 内存限制 125.00MB 题目提供者yeszy 难度省选/NOI- 历史分数100 提交记录 查看题解 标签 福建省历 ...

随机推荐

  1. Javascript 小练习

    --------------------------要收获别人五年才能收获的东西,你就要做好准备,遭受别人五人所遭受的坎坷” // -------------------------------*** ...

  2. 剑指Offer-- 二叉搜索树的第K个结点

    给定一颗二叉搜索树,请找出其中的第k大的结点.例如, 5 / \ 3 7 /\ /\ 2 4 6 8 中,按结点数值大小顺序第三个结点的值为4. /* struct TreeNode { int va ...

  3. Python入门-三级菜单

    作业题目: 三级菜单 作业需求: menu = { '北京':{ '海淀':{ '五道口':{ 'soho':{}, '网易':{}, 'google':{} }, '中关村':{ '爱奇艺':{}, ...

  4. C. Nastya Is Transposing Matrices

    链接 [https://codeforces.com/contest/1136/problem/C] 题意 给你两个规模一样的矩阵 问是否可以通过不断选取A矩阵的子"方正"转置得到 ...

  5. 福州大学软件工程1816 | W班 第10次作业[个人作业——软件产品案例分析]

    作业链接 个人作业--软件产品案例分析 评分细则 本次个人项目分数由两部分组成(课堂得分(老师/助教占比60%,学生占比40%)满分40分+博客分满分60分) 课堂得分和博客得分表 评分统计图 千帆竞 ...

  6. JEECG 不同(角色的)人对同样的字段数据,使用不同的字段验证规则

    JEECG智能开发平台v3 开发指南http://www.jeecg.org/book/jeecg_v3.html jeecg: JEECG是一款基于代码生成器的J2EE快速开发平台,开源界“小普元” ...

  7. TCP 握手和挥手图解(有限状态机)

    1.引言 TCP 这段看过好几遍,老是记不住,没办法找工作涉及到网络编程这块,各种问 TCP .今天好好整理一下握手和挥手过程.献给跟我一样忙碌,找工作的童鞋,欢迎大神批评指正. 2.TCP 的连接建 ...

  8. 配置router列表

    import Vue from "vue"; import VueRouter from 'vue-router'; import Star from '../components ...

  9. java.util.Collections.copy():列表List浅拷贝

    今天同事问我怎样将一个列表(list1)拷贝到另一个列表(list2),然后修改新的列表(list2)不会影响到旧的列表(list1),想了一想,这是深拷贝啊. 可是,除了循环new还有别的办法吗,想 ...

  10. 2017年前小纪(有关http的一些缓存理论知识)

    position的top和bottom的区别:前者基准点定在top,后者基准点定在bottom. for-in 遍历属性的顺序不确定 手机端,line-height对光标大小非常有影响 有些css3属 ...