HDU - 3605 Escape (缩点+最大流/二分图多重匹配)
题意:有N(1<=N<=1e5)个人要移民到M(1<=M<=10)个星球上,每个人有自己想去的星球,每个星球有最大承载人数。问这N个人能否移民成功。
分析:可以用最大流的思路求解该问题,新建源点和汇点,源点与人间加入弧,流量为他想去的星球之和;星球和汇点间加入弧,流量为其承载数量;人和星球间加入弧,流量无限。但是本题中N很大,M却很小,所以想去星球的编号组成的二进制数最多不超过1024,那么可以将N个人缩点。然后跑最大流,满流为N。
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int MAXN =1e4+,maxm =1e6+;
const int INF=0x3f3f3f3f; struct ISAP{
int head[MAXN], nv, n, tot; //nv:编号修改的上限
int num[MAXN], d[MAXN], pre[MAXN], cur[MAXN], q[MAXN];
struct node{
int v, next, cap;
}edge[maxm];
void init(){
memset(head,-,sizeof(head));
tot=;
}
void AddEdge(int u, int v, int cap){
edge[tot].v=v;edge[tot].cap=cap;edge[tot].next=head[u];
head[u]=tot++;
edge[tot].v=u;edge[tot].cap=;edge[tot].next=head[v];
head[v]=tot++;
}
void bfs(int s,int t){
memset(num,,sizeof(num));
memset(d,-,sizeof(d));
int f1=, f2=, i;
q[f1++]=t;
d[t]=;
num[]=;
while(f1>=f2){
int u=q[f2++];
for(i=head[u];i!=-;i=edge[i].next){
int v=edge[i].v;
if(d[v]==-){
d[v]=d[u]+;
num[d[v]]++;
q[f1++]=v;
}
}
}
}
int isap(int s,int t){
memcpy(cur,head,sizeof(cur));
int flow=, i, u=pre[s]=s;
bfs(s,t);
while(d[s]<nv){
if(u==t){
int f=INF, pos;
for(i=s;i!=t;i=edge[cur[i]].v){
if(f>edge[cur[i]].cap){
f=edge[cur[i]].cap;
pos=i;
}
}
for(i=s;i!=t;i=edge[cur[i]].v){
edge[cur[i]].cap-=f;
edge[cur[i]^].cap+=f;
}
flow+=f;
if(flow>=n)
return flow;
u=pos;
}
for(i=cur[u];i!=-;i=edge[i].next)
if(d[edge[i].v]+==d[u]&&edge[i].cap) break;
if(i!=-){
cur[u]=i;
pre[edge[i].v]=u;
u=edge[i].v;
}
else{
if(--num[d[u]]==) break;
int mind=nv;
for(i=head[u];i!=-;i=edge[i].next){
if(mind>d[edge[i].v]&&edge[i].cap){
mind=d[edge[i].v];
cur[u]=i;
}
}
d[u]=mind+;
num[d[u]]++;
u=pre[u];
}
}
return flow;
}
}F; int vis[]; int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int S,T,N,M,u,v,tmp,k;
int op;
while(scanf("%d%d",&N,&M)==){
F.init();
k=;
memset(vis,,sizeof(vis));
for(int i=;i<=N;++i){
int x=;
for(int j=;j<=M;++j){
scanf("%d",&op);
x<<=;
x+=op; //转换为二进制状态
}
vis[x]++;
}
for(int i=;i<=;++i) if(vis[i]) k++; //记录缩点后点数
S=;T=k+M+; F.nv=k+M+,F.n = N;
int id=;
for(int i=;i<=;++i){
if(!vis[i]) continue;
id++;
int sta = i,cnt = vis[i];
for(int j=,t=;j<=sta;j<<=,t++){
if(j&sta) F.AddEdge(id,t+k,INF);
}
F.AddEdge(S,id,cnt);
}
for(int i=;i<=M;++i){
scanf("%d",&tmp);
F.AddEdge(i+k,T,tmp);
}
if(F.isap(S,T)==N) printf("YES\n");
else printf("NO\n");
}
return ;
}
还有一种做法是二分图多重匹配。二分图多重匹配的思路与匈牙利算法接近,也是从以匹配的点中寻找增广路。X部为N个人,Y部为M个星球,每个星球有自己的匹配上限。在时间上,两种实现方法所差不多。
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long LL;
const int maxn = 1e5+,maxm = 2e6+;
int N,M;
struct Node{
int K[];
}link[maxn];
int cnt[];
struct Edge{
int to,next;
}edges[maxm];
int head[maxn],tot;
bool used[];
int limit[]; void init()
{
tot=;
memset(head,-,sizeof(head));
} void AddEdge(int u,int v)
{
edges[tot].to = v;
edges[tot].next = head[u];
head[u] = tot++;
} bool dfs(int u){
int v;
for(int i=head[u];~i;i = edges[i].next){
v = edges[i].to;
if(!used[v]){
used[v]=true;
if(cnt[v]<limit[v]){
link[v].K[cnt[v]++]=u;
return true;
}
for(int j=;j<cnt[v];++j){
if(dfs(link[v].K[j])){
link[v].K[j]=u;
return true;
}
}
}
}
return false;
} bool hungary(){
memset(cnt,,sizeof(cnt));
for(int u=;u<=N;u++){
memset(used,,sizeof(used));
if(!dfs(u)) return false; //只要有一个人不能匹配则失败
}
return true;
} int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int T,u,v,tmp,k;
int op;
while(scanf("%d%d",&N,&M)==){
init();
for(int i=;i<=N;++i){
for(int j=;j<=M;++j){
scanf("%d",&op);
if(op) AddEdge(i,j);
}
}
for(int i=;i<=M;++i) scanf("%d",&limit[i]);
if(hungary()) printf("YES\n");
else printf("NO\n");
}
return ;
}
HDU - 3605 Escape (缩点+最大流/二分图多重匹配)的更多相关文章
- M - Escape - HDU 3605 - (缩点+最大流SAP)
题目大意:2012世界末日来了,科学家发现了一些星球可以转移人口,不过有的人可以在一些星球上生存有的人不行,而且每个星球都有一定的承载量,现在想知道是否所有的人都可以安全转移呢? 输入:首先输入一个N ...
- Hdu 3605 Escape (最大流 + 缩点)
题目链接: Hdu 3605 Escape 题目描述: 有n个人要迁移到m个星球,每个星球有最大容量,每个人有喜欢的星球,问是否所有的人都能迁移成功? 解题思路: 正常情况下建图,不会爆内存,但是T ...
- HDU 3605 Escape (网络流,最大流,位运算压缩)
HDU 3605 Escape (网络流,最大流,位运算压缩) Description 2012 If this is the end of the world how to do? I do not ...
- HDU 3605 Escape(二分图多重匹配问题)
Escape Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Subm ...
- hdu3605 Escape 二分图多重匹配/最大流
2012 If this is the end of the world how to do? I do not know how. But now scientists have found tha ...
- hdu 3605(二分图多重匹配)
Escape Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Subm ...
- HDU3605 Escape —— 二分图多重匹配
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3605 Escape Time Limit: 4000/2000 MS (Java/Others) ...
- 【网络流24题】No.7 试题库问题 (最大流,二分图多重匹配)
[题意] 假设一个试题库中有 n 道试题. 每道试题都标明了所属类别. 同一道题可能有多个类别属性.现要从题库中抽取 m 道题组成试卷.并要求试卷包含指定类型的试题. 试设计一个满足要求的组卷算法. ...
- 网络流24题 第五题 - PowerOJ1740 CodeVS1905 圆桌问题 二分图多重匹配 网络最大流
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - PowerOJ1740 - 有SPJ - 推荐 题目传送门 - CodeVS1905 - 无SPJ - 0% ...
随机推荐
- confirg
如果用户点击确定按钮,则 confirm() 返回 true.如果点击取消按钮,则 confirm() 返回 false.在用户点击确定按钮或取消按钮把对话框关闭之前,它将阻止用户对浏览器的所有输入 ...
- Java 还是 C++?
Java 特别象 C++:由此很自然地会得出一个结论:C++似乎会被Java 取代.但我对这个逻辑存有一些疑问. 无论如何,C++仍有一些特性是Java 没有的.而且尽管已有大量保证,声称Java有一 ...
- Windows编程中回调函数的使用心得(MFC篇)
回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数.回调函数不是由该函数的实现方直接调用,而是在特定 ...
- mysq for visual studio 1.1.1
https://cdn.mysql.com/Downloads/MySQLInstaller/mysql-visualstudio-plugin-1.1.1.msi
- JavaScript------如何查看var变量是否是指定类型
function isArray(a) { //Date,Array,String,Object,Function,Boolean,Number return a.constructor.toStri ...
- IOS开发之自定义键盘
本文转载至 http://blog.csdn.net/majiakun1/article/details/41242069 实际开发过程中,会有自定义键盘的需求,比如,需要添加一个表情键盘.本文提供 ...
- SSM框架---详细整合教程
http://blog.csdn.net/zhshulin/article/details/37956105/
- Android UI开发第三十六篇——使用Volley加载图片列表
Android开发者可能会使用Universal Image Loader或者Square`s newer Picasso这些第三方的库去处理图片的加载,那么Volley是怎么加载图片列表的呢,这一篇 ...
- JStorm开发经验+运维经验总结
1.开发经验总结 ——12 Sep 2014 · 8 revisions 在jstorm中, spout中nextTuple和ack/fail运行在不同的线程中, 从而鼓励用户在nextTuple里 ...
- 【Double】double精度问题和int、long除不尽取舍问题
看了老半天,真心没搞懂,留下几篇文章,后面继续跟进吧.... 一.如何理解double精度丢失问题? - 知乎 https://www.zhihu.com/question/42024389/answ ...