题目链接

给一个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. 网页平面设计 HTML

    网页平面设计HTML基础 1.网页的基本元素:文字.图像.超链接 2.HTML的基本机构head.title.body三部分 <html> <head> <title&g ...

  2. nutch2.3中nutch-site.xml设置说明

    nutch-site.xml是运行nutch的非必须设置文件,也就是说你不设置,nutch照样可以运行. nutch-site.xml是nutch-default.xml的一个客制化文件. nutch ...

  3. hive 配置MySQL库

    chkconfig mysqld on MySQL开机自启动 建库: --hive数据库2create database hive DEFAULT CHARSET utf8 COLLATE utf8_ ...

  4. navicat查看mysql数据表记录数不断变化

    在使用navicat进行数据库管理的时候,在查看表对象的时候会发现,每次刷新,数据表的记录数不断变化,尤其是大表. 对于100万的数据经常会显示九十几万,当然通过count(*)出来的数据是正确的. ...

  5. Struts 2的iterator标签来遍历一个含有双层List的嵌套

    今天碰到一个很有意思的问题,就是需要用Struts 2的iterator标签来遍历一个含有双层List的嵌套. 首先我们从最基础的说起,用iterator标签遍历一个List. 如果Action中有一 ...

  6. Android Every day a new function:two

    分享功能: 效果图: 代码(分享TEXT,视频或者图片设置type即可): @Override protected void onCreate(Bundle savedInstanceState) { ...

  7. php随笔1-php图片处理

    php图片处理的知识内容 upload_image.php: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN ...

  8. jira 解决结果配置

    jira 的配置比较繁琐,有很多的小细节,使用中出现了各种小问题,总结梳理下 1.解决结果 问题1:编辑了任务后,解决结果变成了已解决 找到编辑任务所对应的界面方案,将解决结果字段从界面配置里移除 问 ...

  9. 50行实现简易HTTP服务器

    话说由于一直很懒,所以博客好像也没怎么更新...今天有空就写一下吧. 最近在看node.js的时候开始对http协议感兴趣了,毕竟node一开始就是为了做web服务器而产生的.于是试着想了一下大概的思 ...

  10. J2SE知识点摘记(二十六)

    为了用“集合框架”的额外部分把排序支持添加到 Java 2 SDK,版本 1.2,核心 Java 库作了许多更改.像 String 和 Integer 类如今实现 Comparable 接口以提供自然 ...