题意:有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 (缩点+最大流/二分图多重匹配)的更多相关文章

  1. M - Escape - HDU 3605 - (缩点+最大流SAP)

    题目大意:2012世界末日来了,科学家发现了一些星球可以转移人口,不过有的人可以在一些星球上生存有的人不行,而且每个星球都有一定的承载量,现在想知道是否所有的人都可以安全转移呢? 输入:首先输入一个N ...

  2. Hdu 3605 Escape (最大流 + 缩点)

    题目链接: Hdu 3605  Escape 题目描述: 有n个人要迁移到m个星球,每个星球有最大容量,每个人有喜欢的星球,问是否所有的人都能迁移成功? 解题思路: 正常情况下建图,不会爆内存,但是T ...

  3. HDU 3605 Escape (网络流,最大流,位运算压缩)

    HDU 3605 Escape (网络流,最大流,位运算压缩) Description 2012 If this is the end of the world how to do? I do not ...

  4. HDU 3605 Escape(二分图多重匹配问题)

    Escape Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Subm ...

  5. 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 ...

  6. hdu 3605(二分图多重匹配)

    Escape Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Subm ...

  7. HDU3605 Escape —— 二分图多重匹配

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3605 Escape Time Limit: 4000/2000 MS (Java/Others)    ...

  8. 【网络流24题】No.7 试题库问题 (最大流,二分图多重匹配)

    [题意] 假设一个试题库中有 n 道试题. 每道试题都标明了所属类别. 同一道题可能有多个类别属性.现要从题库中抽取 m 道题组成试卷.并要求试卷包含指定类型的试题. 试设计一个满足要求的组卷算法. ...

  9. 网络流24题 第五题 - PowerOJ1740 CodeVS1905 圆桌问题 二分图多重匹配 网络最大流

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - PowerOJ1740 - 有SPJ - 推荐 题目传送门 - CodeVS1905 - 无SPJ - 0% ...

随机推荐

  1. Java 还是 C++?

    Java 特别象 C++:由此很自然地会得出一个结论:C++似乎会被Java 取代.但我对这个逻辑存有一些疑问. 无论如何,C++仍有一些特性是Java 没有的.而且尽管已有大量保证,声称Java有一 ...

  2. Java多线程基础知识总结

    2016-07-18 15:40:51 Java 多线程基础 1. 线程和进程 1.1 进程的概念 进程是表示资源分配的基本单位,又是调度运行的基本单位.例如,用户运行自己的程序,系统就创建一个进程, ...

  3. [ppurl]从”皮皮书屋”下载电子书的姿势

    (欢迎转载,转载请注明出处:http://blog.csdn.net/hcbbt/article/details/42072545) 写在前面的扯皮 为什么标题的"皮皮书屋"加上了 ...

  4. dropload 使用表

    移动端下拉刷新.上拉加载更多插件 依赖 (dependence) Zepto 或者 jQuery 1.7以上版本,推荐jQuery 2.x版本(二者不要同时引用) Zepto or jQuery 1. ...

  5. Arcgis for Js之GeometryService实现測量距离和面积

    距离和面积的測量时GIS常见的功能.在本节,讲述的是通过GeometryService实现測量面积和距离.先看看实现后的效果: watermark/2/text/aHR0cDovL2Jsb2cuY3N ...

  6. 语法之ADO.NET

    ADO.NET的概念 由于本系列并不是主讲ADO.NET.所以这里笔者只会教上面定义有线连接方式相关的类.不管如何让我们先看一下ADO.NET类相关联的所有基类吧.这样子也方便我们下面的学习. 下面是 ...

  7. AtomicInteger保证线程安全的全局变量

    现有业务场景需要做一个线程间的全局变量,并且实现自增效果. 初始使用了volatile 来保证count的安全性,如下: import java.util.concurrent.ExecutorSer ...

  8. mac同时安装多个jdk

    DK8 GA之后,小伙伴们喜大普奔,纷纷跃跃欲试,想体验一下Java8的Lambda等新特性,可是目前Java企业级应用的主打版本还是JDK6, JDK7.因此,我需要在我的电脑上同时有JDK8,JD ...

  9. 160707、Tomcat 使用 c3p0连接池

    Tomcat 中Jndi是使用Tomcat自带的连接池,由于客户要求,抛弃Tomcat自带的连接池.使用c3p0 .经过几个小时调试,解决方案如下: 环境:Tomcat 6 下面来看Jndi 与 c3 ...

  10. Django 中的自定义分页标签

    目录结构: 1.在应用下,migrations的同级目录创建templatetags目录(主要两个文件,包含__init__.py) 2.创建分页标签(pagetag.py) #!/usr/bin/e ...