POJ 3057 网络流 Evacuation

题意:

有一个n×m的房间,四周每个格子要么是墙要么是门。中间部分是墙或者人。

现在所有人要从房间逃出去,每个人的速度为1,也就是每个单位时间只能向上下左右四个方向走一格。

多个人可以站在同一个格子上,但是每个时刻每个门只能通过一格人,求所有人从房间中逃出去所需要的最少时间。

分析:

把每个人看成一个点,然后把每个时刻和门组成的二元组看成一个点。

如果两点之间连一条边表示这个人在这个时刻从这个门逃出去。

所以我们可以从小到大将时间逐渐加1,直到找到最大匹配为止。

在增加点的时候,可以在之前最大流基础上增广,这样更快。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <vector>
  6 #include <queue>
  7 #include <map>
  8 #define MP make_pair
  9 using namespace std;
 10
 11 typedef pair<int, int> PII;
 12
 13 const int INF = 0x3f3f3f3f;
 14 const int maxh = 15;
 15 const int maxnode = 20000;
 16
 17 char maze[maxh][maxh];
 18 int id[maxh][maxh];
 19
 20 int row, col;
 21
 22 vector<PII> people, doors;
 23
 24 int dx[] = { 1, 0, -1, 0 };
 25 int dy[] = { 0, 1, 0, -1 };
 26
 27 int dist[50][130];  //the distance from every door to people
 28 int steps[maxh][maxh];
 29
 30 bool inline in(int x, int y) { return x >= 0 && x < row && y >= 0 && y < col; }
 31
 32 bool vis[maxh][maxh];
 33
 34 void bfs(PII s)
 35 {
 36     int st = id[s.first][s.second];
 37     steps[s.first][s.second] = 0;
 38     queue<PII> Q;
 39     Q.push(s);
 40     memset(vis, false, sizeof(vis));
 41     vis[s.first][s.second] = true;
 42
 43     while(!Q.empty())
 44     {
 45         PII t = Q.front(); Q.pop();
 46         for(int i = 0; i < 4; i++)
 47         {
 48             int x = t.first + dx[i];
 49             int y = t.second + dy[i];
 50             if(in(x, y) && !vis[x][y] && maze[x][y] == ‘.‘)
 51             {
 52                 vis[x][y] = true;
 53                 dist[st][id[x][y]] = steps[x][y] = steps[t.first][t.second] + 1;
 54                 Q.push(MP(x, y));
 55             }
 56         }
 57     }
 58 }
 59
 60 struct Edge
 61 {
 62     int from, to, cap, flow;
 63     Edge(int u, int v, int c, int f):from(u), to(v), cap(c), flow(f) {}
 64 };
 65
 66 int nodes;
 67 vector<int> G[maxnode];
 68 vector<Edge> edges;
 69
 70 void init()
 71 {
 72     edges.clear();
 73     for(int i = 0; i < nodes; i++) G[i].clear();
 74 }
 75
 76 void AddEdge(int u, int v, int cap)
 77 {
 78     edges.push_back(Edge(u, v, cap, 0));
 79     edges.push_back(Edge(v, u, 0, 0));
 80     int m = edges.size();
 81     G[u].push_back(m - 2);
 82     G[v].push_back(m - 1);
 83 }
 84
 85 int s, t;
 86 bool visit[maxnode];
 87 int d[maxnode], cur[maxnode];
 88
 89 bool BFS()
 90 {
 91     memset(visit, false, sizeof(visit));
 92     queue<int> Q;
 93     Q.push(s);
 94     d[s] = 0;
 95     visit[s] = true;
 96
 97     while(!Q.empty())
 98     {
 99         int u = Q.front(); Q.pop();
100         for(int i = 0; i < G[u].size(); i++)
101         {
102             Edge& e = edges[G[u][i]];
103             int v = e.to;
104             if(!visit[v] && e.cap > e.flow)
105             {
106                 visit[v] = true;
107                 Q.push(v);
108                 d[v] = d[u] + 1;
109             }
110         }
111     }
112
113     return visit[t];
114 }
115
116 int DFS(int u, int a)
117 {
118     if(u == t || a == 0) return a;
119     int flow = 0, f;
120     for(int& i = cur[u]; i < G[u].size(); i++)
121     {
122         Edge& e = edges[G[u][i]];
123         int v = e.to;
124         if(d[v] == d[u] + 1 && (f = DFS(v, min(a, e.cap - e.flow))) > 0)
125         {
126             e.flow += f;
127             edges[G[u][i]^1].flow -= f;
128             flow += f;
129             a -= f;
130             if(a == 0) break;
131         }
132     }
133     return flow;
134 }
135
136 int Maxflow()
137 {
138     int flow = 0;
139     while(BFS())
140     {
141         memset(cur, 0, sizeof(cur));
142         flow += DFS(s, INF);
143     }
144     return flow;
145 }
146
147 void Readuce()
148 {
149     for(int i = 0; i < edges.size(); i++)
150         edges[i].cap -= edges[i].flow, edges[i].flow = 0;
151 }
152
153 int main()
154 {
155     int T; scanf("%d", &T);
156     while(T--)
157     {
158         scanf("%d%d", &row, &col);
159         for(int i = 0; i < row; i++) scanf("%s", maze[i]);
160
161         memset(id, 0, sizeof(id));
162         people.clear(); doors.clear();
163         int psz = 0, dsz = 0;
164         for(int i = 0; i < row; i++)
165             for(int j = 0; j < col; j++)
166             {
167                 if(maze[i][j] == ‘D‘) { doors.push_back(MP(i, j)); id[i][j] = dsz++; }
168                 else if(maze[i][j] == ‘.‘) { people.push_back(MP(i, j)); id[i][j] = psz++; }
169             }
170
171         memset(dist, 0x3f, sizeof(dist));
172         for(int i = 0; i < dsz; i++) bfs(doors[i]);
173         bool unreachable = false;
174         for(int i = 0; i < psz; i++)
175         {
176             bool reach = false;
177             for(int j = 0; j < dsz; j++)
178                 if(dist[j][i] < INF) { reach = true; break; }
179             if(reach == false) { unreachable = true; break; }
180         }
181
182         if(unreachable) { puts("impossible"); continue; }
183
184         int tot_time = 0;
185         s = 0, t = 1;
186         nodes = 2 + psz;
187         init();
188         for(int i = 0; i < psz; i++) AddEdge(s, i + 2, 1);
189
190         int matches = 0;
191         for(;;)
192         {
193             tot_time++;
194             for(int i = 0; i < dsz; i++)
195             {
196                 G[nodes].clear();
197                 AddEdge(nodes, t, 1);
198                 for(int j = 0; j < psz; j++)
199                     if(dist[i][j] <= tot_time) AddEdge(j + 2, nodes, 1);
200                 nodes++;
201             }
202             matches += Maxflow();
203             if(matches == psz) break;
204             Readuce();
205         }
206         printf("%d\n", tot_time);
207     }
208
209     return 0;
210 }

代码君

时间: 2024-11-10 01:10:49

POJ 3057 网络流 Evacuation的相关文章

POJ 3057 Evacuation 二分图匹配

每个门每个时间只能出一个人,那就把每个门拆成多个,对应每个时间. 不断增加时间,然后增广,直到最大匹配. //#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<iostream> #include<

POJ 1149 网络流 合并建图

这个题目我敲了一个简单的EK,这不是难点 难点在于建图,按题目的要求 每个猪圈和顾客都建点的话,那也太多了...我看了Edelweiss里面的缩点方法才建好的图,哎,惭愧啊 实际那些猪圈根本不需要单独建点,猪圈无非就是向顾客输送流量 以及向同时开着的猪圈输送流量,这一步可以直接缩为,当某个猪圈被第一次打开,它里面的流量就全部输送给那个顾客那个点,而且可以叠加,因为每一次猪圈是可以互通的,而且猪圈本身是没有容量限制,如果有限制,那就还得再考虑. 此外,每次对猪圈的接下来的访问者都进行建边.用来输送

POJ 3057 Evacuation

分析: 这是一个时间和门的二元组(t,d)和人p匹配的问题,当我们固定d0时,(t,d0)匹配的人数和t具有单调性. t增加看成是多增加了边就行了,所以bfs处理出p到每个d的最短时间,然后把(t,d)和p连边,按t从小到大 枚举点增广就好了.无解的情况只有一种,某个人无论如何都无法出去. /********************************************************* * --Sakura hirahira mai orite ochite-- * * au

Ombrophobic Bovines (poj 2391 网络流+二分+Floyd)

Language: Default Ombrophobic Bovines Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 15733   Accepted: 3434 Description FJ's cows really hate getting wet so much that the mere thought of getting caught in the rain makes them shake in th

poj 1273 网络流第一题 (pdf链接)

推荐一个学习网络流入门的资料   http://acm.pku.edu.cn/summerschool/gw_netflow.pdf 本题为网络流水题,也是pdf中将网络流的一道题,注意重边即可. #include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <cstdlib> using namespace std; int n,m; lon

Power Network (poj 1459 网络流)

Language: Default Power Network Time Limit: 2000MS   Memory Limit: 32768K Total Submissions: 23407   Accepted: 12267 Description A power network consists of nodes (power stations, consumers and dispatchers) connected by power transport lines. A node

poj 3436 网络流构图经典

ACM Computer Factory Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6012   Accepted: 2083   Special Judge Description As you know, all the computers used for ACM contests must be identical, so the participants compete on equal terms. Th

POJ 3281 网络流dinic算法

B - Dining Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 3281 Appoint description: Description Cows are such finicky eaters. Each cow has a preference for certain foods and drinks, and she wil

POJ 3228 网络流+二分&amp;并查集

点击打开链接 题意:有n个城镇,第一行是金矿和金子数量,然后第二行是装金子的地方和能装的数量,在下面是m条道路,问你选择的道路中最大值最小,使得所有金子运到装金子的地方 思路:最大值最小,根本不用考虑一看就是二分,然后想了想就是个网络流的模型嘛,很简单,被坑了几次道路是双向的,改过之后A掉,然后看了看讨论还可以用并查集写,这里两种方法都写了,先是网络流的直接二分最大值,然后满足条件的边建模型,跑一边就行了 #include <queue> #include <vector> #in