HDU 3605 Escape (网络流,最大流,位运算压缩)
HDU 3605 Escape (网络流,最大流,位运算压缩)
Description
2012 If this is the end of the world how to do? I do not know how. But now scientists have found that some stars, who can live, but some people do not fit to live some of the planet. Now scientists want your help, is to determine what all of people can live in these planets.
Input
More set of test data, the beginning of each data is n (1 <= n <= 100000), m (1 <= m <= 10) n indicate there n people on the earth, m representatives m planet, planet and people labels are from 0. Here are n lines, each line represents a suitable living conditions of people, each row has m digits, the ith digits is 1, said that a person is fit to live in the ith-planet, or is 0 for this person is not suitable for living in the ith planet.
The last line has m digits, the ith digit ai indicates the ith planet can contain ai people most..
0 <= ai <= 100000
Output
Determine whether all people can live up to these stars
If you can output YES, otherwise output NO.
Sample Input
1 1
1
1
2 2
1 0
1 0
1 1
Sample Output
YES
NO
Http
HDU:https://vjudge.net/problem/HDU-3605
Source
网络流,最大流,位运算压缩
题目大意
有n个人和m个星球,每一个人可以适应若干个星球的环境,而每一个星球都有人数上限。现在求能否让所有人都分配到一个其可以适应环境的星球上去。
解决思路
首先如果不管数据范围,这道题的网络流建模还是比较好想的。从源点出发连上所有的人,容量为1,从每一个人连边到其所有能适应的星球,容量为1,再从星球连边到汇点,容量为星球能容纳的人数上限。跑最大流后看看最大流是否与人数相等,如果相等则存在可行解,否则无解。
但要注意到本题的数据范围。人数有100000,这样直接跑最大流是会出问题的。再看一看m的数据范围,诶……只有10。于是我们可以想到一定有非常多的人,他们对所有星球的适应情况是一样的。所以我们可以用位运算的方式,把每一个人对星球的适应情况压缩在一个整数里面,然后统计这个数相同的人的人数,相当于把这些人都看作一个人。然后连边的时候就不是连所有的人,而是连不同的类型,而容量就是这种类型的人的个数,其他建图不变。
另:这里使用Dinic实现最大流,可以参考这篇文章
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
const int maxN=100101;
const int maxM=maxN*70;
const int inf=2147483647;
class Edge
{
public:
int u,v,flow;
};
int n,m;
int cnt;
int tot;
int Head[maxN];
int Next[maxM];
Edge E[maxM];
int depth[maxN];
int cur[maxN];
int Q[maxN];
map<int,int> Cnt;
void Add_Edge(int u,int v,int flow);
bool bfs();
int dfs(int u,int flow);
int main()
{
while (cin>>n>>m)
{
cnt=-1;
tot=0;
memset(Head,-1,sizeof(Head));
Cnt.clear();
for (int i=1;i<=n;i++)
{
int ret=0;
for (int j=1;j<=m;j++)
{
int is;
scanf("%d",&is);
ret=ret+(is<<j);//位运算统计
}
Cnt[ret]++;//Cnt就是统计某一种类型的人有多少个
}
map<int,int>::iterator loop;
for (loop=Cnt.begin();loop!=Cnt.end();loop++)//遍历所有的类型
{
tot++;
for (int i=1;i<=m;i++)//连人与星球
if ((loop->first)&(1<<i))//若这类人都能适应第j个星球,则连边,注意容量为这类人的个数
Add_Edge(tot,Cnt.size()+i,loop->second);
Add_Edge(0,tot,loop->second);//连源点与这类人
}
for (int i=1;i<=m;i++)
{
int flow;
scanf("%d",&flow);//读入每一个星球的人数上限,并连汇点
Add_Edge(tot+i,tot+m+1,flow);
}
int Ans=0;//求解最大流
while (bfs())
{
for (int i=0;i<=tot+m+1;i++)
cur[i]=Head[i];
while (int di=dfs(0,inf))
Ans+=di;
}
if (Ans==n)//若满流,则有解,否则无解
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
void Add_Edge(int u,int v,int flow)
{
cnt++;
Next[cnt]=Head[u];
Head[u]=cnt;
E[cnt].u=u;
E[cnt].v=v;
E[cnt].flow=flow;
cnt++;
Next[cnt]=Head[v];
Head[v]=cnt;
E[cnt].u=v;
E[cnt].v=u;
E[cnt].flow=0;
}
bool bfs()
{
memset(depth,-1,sizeof(depth));
int h=1,t=0;
Q[1]=0;
depth[0]=1;
do
{
t++;
int u=Q[t];
for (int i=Head[u];i!=-1;i=Next[i])
{
int v=E[i].v;
if ((depth[v]==-1)&&(E[i].flow>0))
{
depth[v]=depth[u]+1;
h++;
Q[h]=v;
}
}
}
while (h!=t);
if (depth[tot+m+1]==-1)
return 0;
return 1;
}
int dfs(int u,int flow)
{
if (u==tot+m+1)
return flow;
for (int &i=cur[u];i!=-1;i=Next[i])
{
int v=E[i].v;
if ((depth[v]==depth[u]+1)&&(E[i].flow>0))
{
int di=dfs(v,min(flow,E[i].flow));
if (di>0)
{
E[i].flow-=di;
E[i^1].flow+=di;
return di;
}
}
}
return 0;
}
HDU 3605 Escape (网络流,最大流,位运算压缩)的更多相关文章
- Hdu 3605 Escape (最大流 + 缩点)
题目链接: Hdu 3605 Escape 题目描述: 有n个人要迁移到m个星球,每个星球有最大容量,每个人有喜欢的星球,问是否所有的人都能迁移成功? 解题思路: 正常情况下建图,不会爆内存,但是T ...
- HDU 3605 Escape(状压+最大流)
Escape Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Sub ...
- HDU 3605 Escape 最大流+状压
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=3605 Escape Time Limit: 2000/1000 MS (Java/Others) ...
- hdu 3605 Escape 二分图的多重匹配(匈牙利算法)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3605 Escape Time Limit: 4000/2000 MS (Java/Others) ...
- HDU 3605 Escape(状态压缩+最大流)
http://acm.hdu.edu.cn/showproblem.php?pid=3605 题意: 有n个人和m个星球,每个人可以去某些星球和不可以去某些星球,并且每个星球有最大居住人数,判断是否所 ...
- HDU - 3605 Escape (缩点+最大流/二分图多重匹配)
题意:有N(1<=N<=1e5)个人要移民到M(1<=M<=10)个星球上,每个人有自己想去的星球,每个星球有最大承载人数.问这N个人能否移民成功. 分析:可以用最大流的思路求 ...
- HDU 3605 Escape 最大流
题意: 如果这是2012年世界末日怎么办?我不知道该怎么做.但是现在科学家们已经发现,有些星球上的人可以生存,但有些人却不适合居住.现在科学家们需要你的帮助,就是确定所有人都能在这些行星上生活.输入多 ...
- hdu 1885 Key Task(bfs+位运算)
题意:矩阵中'#'表示墙,'.'表示通路,要求从起点'*'到达终点'X',途中可能遇到一些门(大写字母),要想经过,必须有对应的钥匙(小写字母).问能否完成,若能,花费的时间是多少. 分析:同hdu ...
- hdu 3572 Escape 网络流
题目链接 给一个n*m的图, 里面有一些点, '.'代表空地, '#'代表墙, 不可以走, '@'代表大门, 可以有多个, 'X'代表人, 问所有人都走出大门需要的最短时间, 每一时刻一个格子只能有一 ...
随机推荐
- 【nodejs】让nodejs像后端mvc框架(asp.net mvc )一样处理请求--控制器的声明定义和发现篇(3/8)
文章目录 前情概要 前面文章把路由已经介绍的差不多了,包括url映射,路由选择等.接下来讲一讲controller的一些基本规则 BaseController的所有代码都在这里拉.相当简单. 主要逻辑 ...
- 个人博客作业Week3--必应词典案例分析
第一部分 调研,评测 (软件的bug,功能评测,黑箱测试,第8章 用户调研,12 章软件的用户体验) 下载并使用,按照描述的bug定义,找出几个功能性的比较严重的bug.至少两个.用专业的语言描述( ...
- Linux期末总结
Linux内核学习总结 1.计算机是如何工作的? 存储程序计算机工作模型 X86汇编基础 汇编一个简单的C程序分析其汇编指令执行过程 2.操作系统是如何工作的? 三个法宝——存储程序计算机.函数调用堆 ...
- Linux内核分析作业六
1.阅读理解task_struct数据结构 2.分析fork函数对应的内核处理过程sys_clone,理解创建一个新进程如何创建和修改task_struct数据结构: fork进程的代码 #inclu ...
- 读书笔记(chapter4)
进程调度 4.1多任务 1.多任务系统可以划分为:非抢占式多任务和抢占式多任务: (在此模式下,由调度程序来决定什么时候停止一个进程的运行,以便其他进程能够得到执行机会,这个动作叫抢占: 时间片实际上 ...
- 使用Junit进行单元测试
使用Junit进行单元测试 一.目的和要求 JUnit是一款由Erich Gamma(<设计模式>的作者)和Kent Beck(极限编程的提出者)编写的开源的回归测试框架,供Java编码人 ...
- PAT 1033 旧键盘打字
https://pintia.cn/problem-sets/994805260223102976/problems/994805288530460672 旧键盘上坏了几个键,于是在敲一段文字的时候, ...
- Linux下运行Shell脚本或者可执行文件Executable方法
绝对路径 /xxx/xxx/something.sh /xxx/xxx/executable 相对路径 ./something.sh ./executable 注意:前边得加./,可不是像window ...
- CentOS Mininal 安装VMtools的方法
1. 下载安装CentOS75 的mininal版本 2. 安装完成之后挂在vmtools. 虚拟机管理,安装vmtools即可 3. ssh登录虚拟机. cd /dev 进入到设备系统 mount ...
- ios微信浏览器中video视频播放问题
微信ios只支持几种特定的视频格式,一般使用mp4格式的视频(腾讯官方就是用的这种视频格式)