题目大意:有一个类似于迷宫搜索的图,‘.’代表的是无人的路,'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. [转载]给Jquery动态添加的元素添加事件

    原文地址:给Jquery动态添加的元素添加事件作者:小飞侠 我想很多人都会向我一样曾经 被新元素的事件绑定困惑很久也就是在页面加载完成后给元素绑定了事件,但又新增加的元素上却没有绑定任何事件. js的 ...

  2. php导出excel

    感觉技术掌握的有些太杂了,一会儿鼓捣java,一会儿鼓捣php,一边还搞着.net, maybe this just is life. 此前同事给某县政法委做的一套维稳信息平台,数据库是封装了mysq ...

  3. hibernate的pojo和xml文件

  4. C#表达式树的初步了解

    在很早以前就听说过表达式树了,但并没有去了解它.虽然自己用过linq to sql和linq to entity,但也就用着就用着,并没有去深究c#代码怎么会生成sql代码而不是IL.废话不多说了,开 ...

  5. C++编程思想重点笔记(下)

    上篇请看:C++编程思想重点笔记(上) 宏的好处与坏处 宏的好处:#与##的使用 三个有用的特征:字符串定义.字符串串联和标志粘贴. 字符串定义的完成是用#指示,它容许设一个标识符并把它转化为字符串, ...

  6. Ajax技术详解

    Ajax技术:Ajax描述了一种主要使用脚本(JS)操纵HTTP的web应用架构,它的主要特点是使用脚本操纵HTTP和web服务器进行数据交换,不会导致页面重载.Ajax的核心是JS的XMLHttpR ...

  7. Robot Motion(imitate)

    Robot Motion Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11065   Accepted: 5378 Des ...

  8. cocos基础教程(4)基础概念介绍

    在Cocos2d-x-3.x引擎中,采用节点树形结构来管理游戏对象,一个游戏可以划分为不同的场景,一个场景又可以分为不同的层,一个层又可以拥有任意个可见的游戏节点(即对象,游戏中基本上所有的类都派生于 ...

  9. 第7章 使用RAID与LVM磁盘阵列技术

    章节简述: 您好,此章节为新增加的知识内容,正在努力的排版完善,预习2016年9月中旬完成,感谢您的支持,QQ群:340829. 7.1  磁盘冗余阵列 1988年由加利福尼亚大学伯克利分校发表的文章 ...

  10. 安装ruby

    (这些文章都是从我的个人主页上粘贴过来的,大家也可以访问我的主页 www.iwangzheng.com) 过程中有点小曲折,我们leader是技术大牛,现在我生命中多了个超高智商处女座man了,还有一 ...