题目大意:有一个类似于迷宫搜索的图,‘.’代表的是无人的路,'X'代表有人的点,'#'代表此点不可通过,'@'代表门口。每个位置每一秒钟只能站一个人,每个位置到上下左右点的时间为1,问你所有人能不能出去,能出去输出所有人都出去的最小时间,否则输出-1.

链接:点我

A: 增加源点src,和汇点dest,然后根据每个时间点建出分层图,每个时间对应一层,对于每层图的构造如下

B:给每个格子标 上号Xi, 由于每个格子一次只能占一人,所以把每个格子分为两个点xa,xb,连上容量为1的有向边,对于格子为‘X’的,(如果为第0层的话)在源点src与xa 之间连一条容量为1的有向边,对于格子为'@'的点,在xb与汇点dest连上容量为1的有向边,对于每个格子,(除‘#’外),在xb与其上下左右及其本身 的对应下一层图的xa连上容量为1 的一条有向边

C:具体操作并不是一下子建出分层图,由于时间是未知的,所以枚举时间,做最大流,当最大流小于人数时,时间加一并在原图上增加一层,继续求最大流,直到最大流大于等于人数,这时的时间就是答案

原理懂了,代码也懂了,真自己敲估计还是很难敲出来,等专题训练吧

 /*HDU_1733 Escape*/
/*分层图网络流+枚举时间*/
/*AC代码:171ms*/
#include <iostream>
#include <cstdio>
#include <memory.h>
#include <algorithm>
#define MAXN 20005
#define Lim 75
#define INF (1<<30)
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
using namespace std;
struct Node
{
int x,y;
Node(int x1,int y1)
{x=x1;y=y1;}
Node(){}
};
struct edge
{
int u,v,w,next;
}E[];
int head[MAXN],ecnt;
int gap[MAXN],cur[MAXN],dis[MAXN],pre[MAXN];
int N,M,scr,sink,vn,Ti,Sum,now;
int ans;
int dir[][]={,,,-,,,-,,,};
char map[][];
Node Q[];
int Head,Tail;
bool vis[][];
void Insert(int u,int v,int w)
{
E[ecnt].u=u;
E[ecnt].v=v;
E[ecnt].w=w;
E[ecnt].next=head[u];
head[u]=ecnt++;
E[ecnt].u=v;
E[ecnt].v=u;
E[ecnt].w=;
E[ecnt].next=head[v];
head[v]=ecnt++;
}
bool BFS(Node s)
{
int i,j;
Node u,v;
memset(vis,false,sizeof(vis));
Head=Tail=;
vis[s.x][s.y]=true;
Q[Head++]=s;
while(Head!=Tail)
{
u=Q[Tail++];
if(map[u.x][u.y]=='@') return true;
for(i=;i<;i++)
{
int dx=u.x+dir[i][];
int dy=u.y+dir[i][];
if(dx>=&&dx<N&&dy>=&&dy<M&&map[dx][dy]!='#'&&!vis[dx][dy])
{
vis[dx][dy]=true;
Q[Head++]=Node(dx,dy);
}
}
}
return false;
}
bool OK()
{
bool ok=true;
Node s;
int i,j;
for(i=;i<N&&ok;i++)
{
for(j=;j<M;j++)
{
if(map[i][j]=='X')
{
s.x=i;s.y=j;
if(!BFS(s))
{
ok=false;
break;
}
}
}
}
return ok;
}
void Init()
{
int i,j,u;
memset(head,-,sizeof(head));ecnt=;
for(i=;i<N;i++)
scanf("%s",map[i]);
scr=;sink=;vn=;
Sum=;
for(i=;i<N;i++)
{
for(j=;j<M;j++)
{
if(map[i][j]=='X')
{
Sum++;
u=i*M+j+;
Insert(scr,u,);
}
}
}
now=(M*N);
vn+=now;
}
int Sap(int s,int t,int n)//核心代码(模版)
{
int ans=,aug=INF;//aug表示增广路的流量
int i,v,u=pre[s]=s;
for(i=;i<=n;i++)
{
cur[i]=head[i];
dis[i]=gap[i]=;
}
gap[s]=n;
bool flag;
while(dis[s]<n)
{
flag=false;
for(int &j=cur[u];j!=-;j=E[j].next)//一定要定义成int &j,why
{
v=E[j].v;
if(E[j].w>&&dis[u]==dis[v]+)
{
flag=true;//找到容许边
aug=min(aug,E[j].w);
pre[v]=u;
u=v;
if(u==t)
{
ans+=aug;
while(u!=s)
{
u=pre[u];
E[cur[u]].w-=aug;
E[cur[u]^].w+=aug;//注意
}
aug=INF;
}
break;//找到一条就退出
}
}
if(flag) continue;
int mindis=n;
for(i=head[u];i!=-;i=E[i].next)
{
v=E[i].v;
if(E[i].w>&&dis[v]<mindis)
{
mindis=dis[v];
cur[u]=i;
}
}
if((--gap[dis[u]])==) break;
gap[dis[u]=mindis+]++;
u=pre[u];
}
return ans;
} bool Judge(int Ti)
{
int i,j,k,u,v,a,b,dx,dy;
for(i=;i<N;i++)
{
for(j=;j<M;j++)
{
if(map[i][j]=='#') continue;
u=i*M+j+;
a=(Ti-)*N*M;
b=a+N*M;
u=a+u+;
for(k=;k<;k++)
{
dx=i+dir[k][];
dy=j+dir[k][];
if(dx>=&&dx<N&&dy>=&&dy<M&&map[dx][dy]!='#')
{
v=dx*M+dy+;
v=b+v+;
Insert(u,v,);
}
}
if(map[i][j]=='@')
{
v=b+i*M+j+;
Insert(v,sink,);
}
}
}
vn+=(N*M);
now+=(N*M); //这个now好像没啥用
int t=Sap(scr,sink,vn);
ans+=t;
return ans==Sum;
}
void Solve()
{
if(Sum==) {printf("0\n");return;}
if(!OK()) {printf("-1\n");return;}
ans=Ti=;
while(true)
{
Ti++;
if(Judge(Ti)) break;
}
printf("%d\n",Ti);
}
int main()
{
while(scanf("%d%d",&N,&M)!=EOF)
{
Init();
Solve();
}
return ;
}

hdu 1733 分层网络流 ****的更多相关文章

  1. hdu 2883 kebab 网络流

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2883 Almost everyone likes kebabs nowadays (Here a ke ...

  2. SGU 438 The Glorious Karlutka River =) ★(动态+分层网络流)

    [题意]有一条东西向流淌的河,宽为W,河中有N块石头,每块石头的坐标(Xi, Yi)和最大承受人数Ci已知.现在有M个游客在河的南岸,他们想穿越这条河流,但是每个人每次最远只能跳D米,每跳一次耗时1秒 ...

  3. HDU 3452 Bonsai(网络流之最小割)

    题目地址:HDU 3452 最小割水题. 源点为根节点.再另设一汇点,汇点与叶子连边. 对叶子结点的推断是看度数是否为1. 代码例如以下: #include <iostream> #inc ...

  4. hdu 3572 Escape 网络流

    题目链接 给一个n*m的图, 里面有一些点, '.'代表空地, '#'代表墙, 不可以走, '@'代表大门, 可以有多个, 'X'代表人, 问所有人都走出大门需要的最短时间, 每一时刻一个格子只能有一 ...

  5. HDU 3667 Transportation(网络流之费用流)

    题目地址:HDU 3667 这题的建图真是巧妙...为了保证流量正好达到k.须要让每一次增广到的流量都是1,这就须要把每一条边的流量都是1才行.可是每条边的流量并非1,该怎么办呢.这个时候能够拆边,反 ...

  6. HDU 5988最小网络流(浮点数)

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5988 哇,以前的模版一直T,加了优先队列优化才擦边过. 建图很好建,概率乘法化成概率加法不 ...

  7. Leapin' Lizards [HDU - 2732]【网络流最大流】

    题目链接 网络流直接最大流就是了,只是要拆点小心一个点的流超出了原本的正常范围才是. #include <iostream> #include <cstdio> #includ ...

  8. hdu 4292 Food 网络流

    题目链接 给你f种食物, 以及每种食物的个数, d种饮料, 以及个数, n个人, 以及每个人可以接受的食物种类和饮料种类. 每个人必须得到一种食物和一种饮料. 问最后得到满足的人的个数. 因为一个人只 ...

  9. hdu 4289 Control 网络流

    题目链接 给出一些点, 每个点有一个权值, 给出一些边, 起点以及终点, 去掉一些点使得起点和终点不连通, 求最小的val. 拆点, 把一个点s拆成s和s', 之间建一条边, 权值为点权. 对于一条边 ...

随机推荐

  1. SQL防注入程序

    1.在Global.asax.cs中写入: protected void Application_BeginRequest(Object sender,EventArgs e){      SqlIn ...

  2. IIS负载均衡-Application Request Route详解第一篇: ARR介绍(转载)

    IIS负载均衡-Application Request Route详解第一篇: ARR介绍 说到负载均衡,相信大家已经不再陌生了,本系列主要介绍在IIS中可以采用的负载均衡的软件:微软的Applica ...

  3. String与Date、Timestamp互转

    一.String与Date(java.util.Date)互转 1.1 String -> Date String dateStr = "2010/05/04 12:34:23&quo ...

  4. JAVA 利用JNI加密class文件/自定义ClassLoader 类

    利用 JNI 对bytecode 加密.不影响java程序员的正常开发.09年的时候写的,现在拿出来晒晒————————————————————————————混淆才是王道,如果混淆再加密就更酷了.. ...

  5. Web基础架构:负载均衡和LVS

    在大规模互联网应用中,负载均衡设备是必不可少的一个节点,源于互联网应用的高并发和大流量的冲击压力,我们通常会在服务端部署多个无状态的应用服务器和若干有状态的存储服务器(数据库.缓存等等). 一.负载均 ...

  6. C++中构造函数详解及显式调用构造函数

    C++构造函数详解及显式调用构造函数                                         c++类的构造函数详解                        一. 构造函 ...

  7. linux学习笔记 2013-09-02

    1,解压一个tar.gz文件夹 tar -xvzf  filename.tar.gz 2,删除一个文件夹下所有的文件 rm -rf * 3,安装文件 sudo apt-get install XXX. ...

  8. Clustering by fast search and find of density peaks

    参考:http://www.52ml.net/16296.html 这个算法的优点就在于,它首先一步就能找到聚类中心,然后划分类别.而其他算法需要反复迭代才能找到中心聚类. 就是不知道代码该怎么写.. ...

  9. MySQL查询测试经验

    测试表geoinfo,整个表超过1100万行,表结构: CREATE TABLE `geoinfo` ( `objectid` ) NOT NULL AUTO_INCREMENT , `latitud ...

  10. 【Spring】Spring系列5之Spring支持事务处理

    5.Spring支持事务处理 5.1.事务准备 以上代码结构与AOP的前置通知.返回通知.异常通知.后置通知一样. 5.2.声明式事务 5.2.1.基于注解 5.2.2.基于配置文件 5. 3.事务传 ...