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 }
代码君

 

posted @ 2015-09-08 22:46  AOQNRMGYXLMV  阅读(207)  评论(0编辑  收藏  举报