题目描述

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

有一天来了n个客人,每个客人说出了自己喜欢哪些房间,喜欢哪道菜。但是很不幸,可能做不到让所有顾客满意(满意的条件是住进喜欢的房间,吃到喜欢的菜)。

这里要怎么分配,能使最多顾客满意呢?

解析

学了匈牙利,还是讲一个匈牙利的做法。

先说一点,目前并没有找到匈牙利二分图匹配做法完全正确的例子。

分析一下思路问题。

最开始我的思路是直接匹配房和菜,交上去只有40分,仔细思考发现这样一个细节:如果直接匹配房菜,实际上可以把匹配边抽象成一个人,那么在匈牙利找出一条增广路时,会把之前配对的房菜弃用,通俗的讲就是这对房菜其中一个再也不会被这个人使用,然鹅我们并不具体知道是哪一个,而且对于把边抽象成人这个说法又不太准确,毕竟有可能边连的比人还多。而真实情况是,这个人既有可能换房,也有可能换菜,我们要分别考虑。能对4个点已经很不错了。

所以,我们需要建两个图,把人记下来当作未匹配点,分别对菜、人和人、房同步进行二分图匹配。同步即,此时进行增广的起始点为同一个人。这样依次对所有人进行增广,跑一遍匈牙利算法,就可得出最大匹配。

这样还是错的,我就很纳闷,仔细一想,发现问题还是出现在相似的地方。两边同步进行二分图匹配时,我们需要考虑更多。我们发现当一个人无法进行增广时,他有可能是在其中一张图上无法增广,有可能在两张图上都无法增广。显然如果其中一张图无法增广,另一张图如果你还增广,就相当于这个人只选了一个东西,或者菜或者房,那显然不符合题目要求。所以我们索性就不管这个人了,直接跳过这个人不增广他,继续往后面的人增广。

如果这么写的话,是可以A这道题的,但是依然有人hack掉了。

至于被hack的原因,补充一点个人想法:

注意到上面提到的跳过无法增广的人的思路,实际上细想还是存在问题。试想,是否存在一种情况,我们选择了这个本应被跳过的人,然后挤掉了之前的某个人,会使得整体更优?按道理来讲我觉得是存在的,也就是说这种做法是有后效性的,或许某种后面的决策会影响到之前的决策,并且还会使整体更优?那么如果这样讲,匈牙利是做不了这题的,匈牙利算法本身就无法胜任(毕竟哪也没写它可以同时处理两张有交叉的二分图)。

仅个人理解,如有错误,望dalao指正。

参考代码

这回就真的只是参考了,能AC,但是不一定完全正确。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<bitset>
#define N 501
using namespace std;
inline int read()
{
int f=1,x=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
int a[N][N],b[N][N],n,p,q,f1[N],f2[N],res1[N],res2[N];
vector<int> g1[N],g2[N];
bitset<N> v1,v2;
inline bool dfs1(int x)//正宗二分图匹配
{
for(register int i=0;i<g1[x].size();++i){
int y=g1[x][i];
if(v1[y]) continue;
v1[y]=1;
if(!f1[y]||dfs1(f1[y])){
f1[y]=x;
return 1;
}
}
return 0;
}
inline bool dfs2(int x)
{
for(register int i=0;i<g2[x].size();++i){
int y=g2[x][i];
if(v2[y]) continue;
v2[y]=1;
if(!f2[y]||dfs2(f2[y])){
f2[y]=x;
return 1;
}
}
return 0;
}
int main()
{
n=read(),p=read(),q=read();
for(int i=1;i<=n;++i)
for(int j=1;j<=p;++j) scanf("%d",&a[i][j]);
for(int i=1;i<=n;++i)
for(int j=1;j<=q;++j) scanf("%d",&b[i][j]);
for(int i=1;i<=n;++i)
for(int j=1;j<=p;++j)
for(int k=1;k<=q;++k)
//建图,这边我建图稍微麻烦了点,但是比较好理解
if(a[i][j]) g1[i].push_back(j+n),g1[j+n].push_back(i);
else if(b[i][k]) g2[i].push_back(k+n),g2[k+n].push_back(i);
int ans=0;
for(int i=1;i<=n;++i){
v1.reset(),v2.reset();
memcpy(res1,f1,sizeof(f1));
memcpy(res2,f2,sizeof(f2));
if(dfs1(i)&&dfs2(i)) ans++;
else{
memcpy(f1,res1,sizeof(f1));//回溯过程
memcpy(f2,res2,sizeof(f2));
}
}
cout<<ans<<endl;
return 0;
}

P1402 酒店之王[网络瘤(正解)/匈牙利(错解)]的更多相关文章

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

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

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

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

  3. P1402 酒店之王

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

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

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

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

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

  6. P1402 酒店之王 最大流

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

  7. luogu P1402 酒店之王

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

  8. BZOJ 1711 吃饭dining/Luogu P1402 酒店之王 拆点+最大流流匹配

    题意: (吃饭dining)有F种食物和D种饮料,每种食物或饮料只能供一头牛享用,且每头牛只享用一种食物和一种饮料.现在有n头牛,每头牛都有自己喜欢的食物种类列表和饮料种类列表,问最多能使几头牛同时享 ...

  9. P1402 酒店之王 网络流

    大水题,我自己瞎做就做出来了,没啥说的,zz建图,就是板子. 题干: 题目描述 XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化.由于很多来住店的旅客有自己喜好的房间色调.阳光等, ...

随机推荐

  1. 高级UI-滤镜和颜色通道

    滤镜在图片处理里面有很多的运用,尤其是相机使用了大量的滤镜,通过对颜色通道的调和,可以呈现出各种各样的效果 对图像进行一定的过滤加工处理,使用Paint设置滤镜效果 很多高级UI使用时候需要关闭硬件加 ...

  2. 微信小程序 与后台交互----获取服务器时间

    index.wxml代码 <!--index.wxml--> <view class="container"> <text>{{date}}&l ...

  3. Python MySQLdb 学习总结(转)

    转自http://www.cnblogs.com/coser/archive/2012/01/12/2320741.html 感谢@糖拌咸鱼 任何应用都离不开数据,所以在学习python的时候,当然也 ...

  4. Java-Readable

    import java.nio.*; import java.util.*; import static net.mindview.util.Print.*; public class RandomW ...

  5. BugkuCTF~Misc~WriteUp

    1.签到 get flag: Qftm{You should sign in} 2.这是一张单纯的图片 查看图片十六进制 提去特殊字符串进行解码 get flag: key{you are right ...

  6. ubuntu16.04+cuda9.0_cudnn7.5+tensorflow-gpu==1.12.0

    1.查找可用的tensorflow源,该命令运行后终端会输出所有可用的源 anaconda search -t conda tensorflow 2.这里name是上一步中输出源的tensorflow ...

  7. libevent实现对管道的读写操作

    读管道: #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/t ...

  8. 引用js文件中的函数调用

    开发中遇到一个问题,代码demo如下: test.js文件内容: var b = getHomeCity(); Test.html文件内容: <!DOCTYPE html> <htm ...

  9. MVC与MTV模型

    MVC与MTV模型 MVC Web服务器开发领域里著名的MVC模式,所谓MVC就是把Web应用分为模型(M),控制器(C)和视图(V)三层,他们之间以一种插件式的.松耦合的方式连接在一起,模型负责业务 ...

  10. c# webapi 过滤器token、sign认证、访问日志

    1.token认证 服务端登录成功后分配token字符串.记录缓存服务器,可设置有效期 var token = Guid.NewGuid().ToString().Replace("-&qu ...