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'代表人, 问所有人都走出大门需要的最短时间, 每一时刻一个格子只能有一 ...
随机推荐
- Appium Studio 初体验(windows做ios自动化,录制appium脚本)
偶然的机会遇到了这个工具——Appium Studio, 在官网是这么解释的 Get your Appium testing projects going within minutesInstall ...
- vim命令记录
最近开始用vim作为日常编辑器,由于vim的命令过多,现在记录一下
- 求去掉一条边使最小割变小 HAOI2017 新型城市化
先求最小割,然后对残量网络跑Tarjan.对于所有满流的边,若其两端点不在同一个SCC中,则这条边是满足条件的. 证明见 来源:HAOI2017 新型城市化
- 访谈:BugPhobia’s Brief Communication
0x01 :采访的学长简介 If you weeped for the missing sunset, you would miss all the shining stars 梁野,北京航空航天大学 ...
- linux及安全第六周总结
进程控制块pcb——task_struct 操作系统三大功能: 进程管理(核心) 内存管理 文件系统 为了管理进程,内核必须对每个进程进行清晰的描述,进程描述符提供了内核所需了解的进程信息: 进程状态 ...
- Linux内核分析——第四章 进程调度
第四章 进程调度 4.1 多任务 1.多任务操作系统就是能同时并发的交互执行多个进程的操作系统. 2.多任务操作系统使多个进程处于堵塞或者睡眠状态,实际不被投入执行,这些任务尽管位于内存,但是并不处于 ...
- 【转】GPS定位准确度CEP、RMS
转自:http://blog.sina.com.cn/s/blog_70f96fda0101lcb9.html CEP和RMS是GPS的定位准确度(俗称精度)单位,是误差概率单位.就拿2.5M CEP ...
- PAT 甲级 1134 Vertex Cover
https://pintia.cn/problem-sets/994805342720868352/problems/994805346428633088 A vertex cover of a gr ...
- Gradle vs Maven Comparison
https://gradle.org/maven-vs-gradle/ Maven需要搭建本地仓库:Gradle直接集成了仓库. ??? 从Maven转移到Gradle,对于如何使用类似于Maven的 ...
- Notepad++和Sublime单词首字符大小写转化问题