题目链接

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

先dfs判断是否每个人都能走出, 如果有人不能, 直接输出-1。

从小到大枚举时间, 对于枚举的时间t, 每个格子i, j向它四周以及他本身建边, ( i*m+j+(t-1)*nm, x*m+y+t*nm, 1), 这样就相当于t-1时刻的点向t时刻的点连了一条边。 然后每个出口向汇点连边, (x*m+y+t*nm, 汇点, 1)。 源点向0时刻的每个人连边, 只连一次。

这样每次都跑一遍网络流, 如果结果ans等于人数sum, 那么说明这个时刻是最小时刻, 需要注意的是, 如果结果不等于人数, 那么sum -= ans。

具体看代码。

 #include<bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define mem1(a) memset(a, -1, sizeof(a))
#define mem2(a) memset(a, 0x3f, sizeof(a))
const int inf = ;
const int dir[][] = { {-, }, {, }, {, -}, {, },{, } };
const int maxn = 2e6+;
int q[maxn*], head[maxn*], dis[maxn/], s, t, m, n, vis[][], num, flag, sum;
char c[][];
struct node
{
int to, nextt, c;
node(){}
node(int to, int nextt, int c):to(to), nextt(nextt), c(c){}
}e[maxn*];
void init() {
num = flag = sum = ;
mem1(head);
}
void add(int u, int v, int c) {
e[num] = node(v, head[u], c); head[u] = num++;
e[num] = node(u, head[v], ); head[v] = num++;
}
int bfs() {
mem(dis);
dis[s] = ;
int st = , ed = ;
q[ed++] = s;
while(st<ed) {
int u = q[st++];
for(int i = head[u]; ~i; i = e[i].nextt) {
int v = e[i].to;
if(!dis[v]&&e[i].c) {
dis[v] = dis[u]+;
if(v == t)
return ;
q[ed++] = v;
}
}
}
return ;
}
int dfs(int u, int limit) {
if(u == t) {
return limit;
}
int cost = ;
for(int i = head[u]; ~i; i = e[i].nextt) {
int v = e[i].to;
if(e[i].c&&dis[v] == dis[u]+) {
int tmp = dfs(v, min(limit-cost, e[i].c));
if(tmp>) {
e[i].c -= tmp;
e[i^].c += tmp;
cost += tmp;
if(cost == limit)
break;
} else {
dis[v] = -;
}
}
}
return cost;
}
int dinic() {
int ans = ;
while(bfs()) {
ans += dfs(s, inf);
}
return ans;
}
// 上面是模板
int judge(int x, int y) {
if(x>=&&x<n&&y>=&&y<m&&c[x][y]!='#'&&!vis[x][y])
return ;
return ;
} int dfs1(int x, int y) {
for(int i = ; i<; i++) {
int tmpx = x+dir[i][];
int tmpy = y+dir[i][]; //判断能否走出
if(judge(tmpx, tmpy)) {
if(c[tmpx][tmpy]=='@')
return ;
vis[tmpx][tmpy] = ;
if(dfs1(tmpx, tmpy))
return ;
}
}
return ;
} int ok(int deep) { //枚举时间, 每一次枚举, 都在原有的图的基础上继续建边,因为原图已经跑过一遍最大流, 所以每次结束后
int nm = n*m; //总人数都应该减去每一次的结果, 意思是已经有那么多的人跑了出去。
for(int i = ; i<n; i++) {
for(int j = ; j<m; j++) {
if(c[i][j] == '@') {
add(i*m+j+nm*deep+, t, ); //对于每一时刻, 出口都要向汇点建边。
continue;
}
if(c[i][j]=='#')
continue;
for(int k = ; k<; k++) {
int x = i+dir[k][];
int y = j+dir[k][];
if(judge(x, y)) {
add(i*m+j+(deep-)*nm+, x*m+y+deep*nm+, ); //前一时刻的点向这一时刻建边。
}
}
}
}
int ans = dinic();
if(ans == sum)
return ;
sum -= ans; //这里十分重要啊....
return ;
} int main()
{
while(~scanf("%d%d", &n, &m)) {
init();
for(int i = ; i<n; i++)
scanf("%s", c[i]);
s = , t = ;
for(int i = ; i<n; i++) {
for(int j = ; j<m; j++) {
if(c[i][j] == 'X') {
add(s, i*m+j+, ); //源点向0时刻的每一个人连边
mem(vis);
sum++;
if(!dfs1(i, j)) {
flag = ;
}
}
}
}
if(flag) {
puts("-1");
continue;
}
mem(vis);
int ans;
for(ans = ; ; ans++) {
if(ok(ans)) //枚举时间
break;
}
cout<<ans<<endl;
}
}

hdu 3572 Escape 网络流的更多相关文章

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

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

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

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

  3. HDU 3572 Task Schedule(拆点+最大流dinic)

    Task Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) To ...

  4. HDU 3533 Escape(大逃亡)

    HDU 3533 Escape(大逃亡) /K (Java/Others)   Problem Description - 题目描述 The students of the HEU are maneu ...

  5. HDU 3572 Task Schedule (最大流)

    C - Task Schedule Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u S ...

  6. hdu 3572 Task Schedule 网络流

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3572 Our geometry princess XMM has stoped her study i ...

  7. HDU 3036 Escape 网格图多人逃生 网络流||二分匹配 建图技巧

    题意: 每一个' . '有一个姑娘, E是出口,'.'是空地 , 'X' 是墙. 每秒钟每一个姑娘能够走一步(上下左右) 每秒钟每一个出口仅仅能出去一个人 给定n*m的地图, 时限T 问全部姑娘是否能 ...

  8. hdu 3572 : Task Schedule (网络流)

    题目链接 题意: 有M个机器,N个任务 对第i个任务,需要在[Si,Ei]这段时间内恰有Pi天被process 每天最多有M个机器同时工作 每一天,一个任务若被process,那么它恰占用一个机器. ...

  9. 图论--网络流--最大流 HDU 3572 Task Schedule(限流建图,超级源汇)

    Problem Description Our geometry princess XMM has stoped her study in computational geometry to conc ...

随机推荐

  1. C#扩展方法的理解 (转)

    “扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型.” 这是msdn上说的,也就是你可以对String,Int,DataRow,DataTable等这些 ...

  2. 将控制台程序做成windows服务

    一:添加windows服务 二:修改XXXInstaller1的StartType=Automatic,修改ProcessInstaller1的Account=LocalSystem 三:在progr ...

  3. vb mid 函数使用说明

    Mid就是从一个字符串中取子字符串,比如a="aabbcc",我们想取出"bb"就可以用Mid("aabbcc",3,2)Mid有3个参数, ...

  4. erlang学习笔记(1)

    提示符erl 注释% comment 表达式123456789 * 123456789. 变量(单一赋值)X = 123456789.X.Y = X * X * X.Y.f(). 整数浮点数X = 5 ...

  5. startup_LPC17XX.s 启动文件分析

    工程中startup_LPC17XX.s是M3的启动文件,启动文件由汇编语言写的,它的作用一般是下面这几个: 1)堆和栈的初始化 2)中断向量表定义 3)地址重映射及中断向量表的转移 4)设置系统时钟 ...

  6. Android手机app启动的时候第一个Activity必须是MainActivity吗

    原文:Android手机app启动的时候第一个Activity必须是MainActivity吗 Android手机APP启动的第一个Activity是可以自己设置的,不是必须的MainActivity ...

  7. [C#]Stream.Write Extension Method

    在处理Stream型态时常会使用到Stream.Write这个方法,每次都会有种疑问就是,大多数的处理都是要将Buffer整个写入,為何偏偏每次都要将索引带0,长度带為Buffer的大小呢?另外在处理 ...

  8. 发布MFC ActiveX控件并实现自动更新

    一.        引言 上一篇我们讲了如何使用 VC 2005来开发 MFC ActiveX控件,我们开发 ActiveX控件最终目的是将 ActiveX控件发布出来并嵌入在 Web网页中,随着控件 ...

  9. cloud computing platform,virtual authentication encryption

    Distributed Management Task Forcevirtual Ethernet port aggregator encryption,authenticating,local ac ...

  10. python SyntaxError: Non-ASCII character '\xd5' in file

    我使用的是python2.7, 在pycharm想运行程序,但是却报出了SyntaxError: Non-ASCII character '\xd5' in file 原因是因为源码中包含了中文注释, ...