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% ...
随机推荐
- SVD分解与数据压缩
SVD的几何解释:http://blog.csdn.net/dinosoft/article/details/37884597 上文未证明为什么AAT的特征向量就是要找的v 这里有个简单的说明: SV ...
- .NET开发笔记--对config文件的操作(2)
1.前台代码 sys_channel_edit.aspx <tbody id="item_box"> <asp:Repeater ID="rptList ...
- CentOS7 以下安装Mysql MMM
參考文档 參考1 參考2 * 一. 规划 server IP 作用 monitor 192.168.1.210 监控server master-001 192.168.1.211 读写主机001 ma ...
- Social Network 社交网络分析
Social Network 社交网络分析 一:什么是SNA-社交网络分析 社交网络分析的威力何在?我想几个案例来说明. 案例1:对一个毫无了解的组织(这个组织可以是一个公司,亦或是一个组织),如果能 ...
- spring-redis SortedSet类型成员的过期时间处理
redis默认是只支持简单key的过期处理的,像SortedSet类型,也是针对整个set的过期处理,不支持对set的某个成员的过期处理: 为了解决这个问题,做法如下: 1.存储key及值信息到red ...
- Python标准库:内置函数delattr(object, name)
本函数是用来删除对象的属性,比方在函数setattr()里加入的属性,就能够利用这个函数来删除. 參数object是一个对象,參数name是一个字符串,但这个字符串必须是对象的属性.比方delattr ...
- JavaScript------日期和时间戳的相互转换
var date = new Date(); 日期转时间戳 Number(date)或者date.getTime(); //只是转换成了纯数字的时间戳,例如:1498144203861需要转换才能使用 ...
- 【Cygwin】Windows下使用linux命令
我参阅了这份文章: 让windows cmd也用上linux命令 原文时间有点久了,Cygwin也更新了... 所以我的做法简单了很多... 到Cygwin官网下载安装包:https://cygwin ...
- CentOS 7 64位 安装 PostgreSQL 9.2整理
centos版本 LSB Version: :core-4.1-amd64:core-4.1-noarchDistributor ID: CentOSDescription: CentOS Linux ...
- 如何转义CSV文件中的逗号
CSV全称是:Comma Separated Values 或者 Character Separated Values. 尽管第一种说法更常见,但我觉得还是第二种说法更确切一些,因为你可以使用其它字符 ...