题目大意:有一个类似于迷宫搜索的图,‘.’代表的是无人的路,'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. 转 web项目中的web.xml元素解析

    转 web项目中的web.xml元素解析 发表于1年前(2014-11-26 15:45)   阅读(497) | 评论(0) 16人收藏此文章, 我要收藏 赞0 上海源创会5月15日与你相约[玫瑰里 ...

  2. win7打开网页老是提示下载网页解决办法

    方法:我的系统是windows 7 旗舰版, 解决方法可以自己手动去修复,方法是进入命令窗口. 开始--运行--cmd--sfc.exe--sfc/scannow   修复一下!

  3. ls -alrth 及ls 详解

    idcdpi  抓包过程中 用了命令  ls   - alrth :命令,所以回头重新学习 ls命令 linux ls和 ll 命令 标签: linuxsocketssolarisbash出版扩展 2 ...

  4. 《深入PHP与jQuery开发》读书笔记——Chapter2

    Pro PHP and jQuery Chapter2 总结 1.理解jQuery脚本的基本行为 jQuery事实上沿用了JavaScript的那一套东西,几乎所有方法都支持链式调用,也就是说方法可以 ...

  5. zstu.4022.旋转数阵(模拟)

    旋转数阵 Time Limit: 1 Sec  Memory Limit: 64 MB Submit: 1477  Solved: 102 Description 把1到n2的正整数从左上角开始由外层 ...

  6. URL编码表,URL编码大全

    url编码是一种浏览器用来打包表单输入的格式. 定义 url编码是一种浏览器用来打包表单输入的格式.浏览器从表单中获取所有的name和其中的值 ,将它们以name/value参数编码(移去那些不能传送 ...

  7. android webview删除缓存

    [1].[代码] 删除保存于手机上的缓存. 跳至 [1] [2] [3] 01 // clear the cache before time numDays     02 private int cl ...

  8. JAVA-- M选N的组合算法

      M选N的组合算法 只要每个数字出现一次就可以   举例 :也就是说123与321和213属于重复 只算一组  此算法已经排除了重复数据  应用--彩票的注数算法 本程序的思路是开一个数组b,其长度 ...

  9. 【OpenStack】OpenStack系列10之Horizon详解

    一.参考其他资料即可.可以采用haproxy+apache+horizon方式部署,haproxy/httpd支持ssl.

  10. 面向侧面的程序设计AOP-------《三》.Net平台AOP技术概览

    本文转载自张逸:晴窗笔记 .Net平台与Java平台相比,由于它至今在服务端仍不具备与unix系统的兼容性,也不具备类似于Java平台下J2EE这样的企业级容器,使得.Net平台在大型的企业级应用上, ...