[POJ3057]Evacuation(二分图匹配,BFS,二分,好题)

题目链接:http://poj.org/problem?id=3057

题意:《挑战》P230的题。

首先预处理出所有人到所有门的最短距离dis(pxi,pyi,dxj,dyj),然后二分答案。

拿二分出的时间t判断,判断的时候把每一个门拆成t个点,与人连起来,求最大匹配,看匹配结果是否满足与总人数相等。

因为要保证每一个人都在某一个门的一秒出去,所以可以用上述建图方法保证。

RE了不知道在哪里。。

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <iomanip>
  4 #include <cstring>
  5 #include <climits>
  6 #include <complex>
  7 #include <cassert>
  8 #include <cstdio>
  9 #include <bitset>
 10 #include <vector>
 11 #include <deque>
 12 #include <queue>
 13 #include <stack>
 14 #include <ctime>
 15 #include <set>
 16 #include <map>
 17 #include <cmath>
 18 using namespace std;
 19 
 20 const int maxn = 50500;
 21 const int maxm = 33;
 22 int nx, ny;
 23 int G[maxm][maxn];
 24 int linker[maxn];
 25 bool vis[maxn];
 26 
 27 bool dfs(int u) {
 28     for(int v = 0; v < ny; v++) {
 29         if(G[u][v] && !vis[v]) {
 30             vis[v] = 1;
 31             if(linker[v] == -1 || dfs(linker[v])) {
 32                 linker[v] = u;
 33                 return 1;
 34             }
 35         }
 36     }
 37     return 0;
 38 }
 39 
 40 int hungary() {
 41     int ret = 0;
 42     memset(linker, -1, sizeof(linker));
 43     for(int u = 0; u < nx; u++) {
 44         memset(vis, 0, sizeof(vis));
 45         if(dfs(u)) ret++;
 46     }
 47     return ret;
 48 }
 49 
 50 
 51 typedef struct Node {
 52     int x, y, st;
 53     Node() {}
 54     Node(int x, int y, int st) : x(x), y(y), st(st) {}
 55 }Node;
 56 
 57 const int fx[5] = {0, 0, 1, -1};
 58 const int fy[5] = {1, -1, 0, 0};
 59 int n, m;
 60 char mp[maxm][maxm];
 61 int dis[maxm][maxm][maxm][maxm];
 62 vector<int> px, py;
 63 vector<int> dx, dy;
 64 bool done[maxm][maxm];
 65 
 66 bool board(int x, int y) {
 67     return x >= 0 && x < n && y >= 0 && y < m;
 68 }
 69 
 70 void bfs(int sx, int sy) {
 71     queue<Node> q;
 72     q.push(Node(sx, sy, 0));
 73     memset(done, 0, sizeof(done));
 74     done[sx][sy] = 1;
 75     while(!q.empty()) {
 76         Node tmp = q.front(); q.pop();
 77         if(mp[tmp.x][tmp.y] == 'D') {
 78             dis[sx][sy][tmp.x][tmp.y] = tmp.st;
 79             continue;
 80         }
 81         for(int i = 0; i < 4; i++) {
 82             int xx = tmp.x + fx[i];
 83             int yy = tmp.y + fy[i];
 84             if(board(xx, yy) && mp[xx][yy] != 'X' && !done[xx][yy]) {
 85                 done[xx][yy] = 1;
 86                 q.push(Node(xx, yy, tmp.st+1));
 87             }
 88         }
 89     }
 90 }
 91 
 92 int id(int t, int i) {
 93     return t * dx.size() + i;
 94 }
 95 
 96 bool ok(int t) {
 97     nx = px.size();
 98     ny = t * dx.size();
 99     memset(G, 0, sizeof(G));
100     for(int i = 0; i < px.size(); i++) {
101         for(int j = 0; j < dx.size(); j++) {
102             int& d = dis[px[i]][py[i]][dx[j]][dy[j]];
103             if(d == -1) continue;
104             for(int h = 0; h < t - d; h++) {
105                 G[i][id(h, j)] = 1;
106             }
107         }
108     }
109     return hungary() == nx;
110 }
111 
112 int main() {
113     // freopen("in", "r", stdin);
114     int T;
115     scanf("%d", &T);
116     while(T--) {
117         scanf("%d%d",&n,&m);
118         memset(mp, 0, sizeof(mp));
119         memset(dis, -1, sizeof(dis));
120         px.clear(); py.clear();
121         dx.clear(); dy.clear();
122         for(int i = 0; i < n; i++) scanf("%s", mp[i]);
123         for(int i = 0; i < n; i++) {
124             for(int j = 0; j < m; j++) {
125                 if(mp[i][j] == '.') {
126                     px.push_back(i);
127                     py.push_back(j);
128                 }
129                 else if(mp[i][j] == 'D') {
130                     dx.push_back(i);
131                     dy.push_back(j);
132                 }
133             }
134         }
135         for(int i = 0; i < px.size(); i++) bfs(px[i], py[i]);
136         int lo = -1, hi = n * m + 1;
137         while(lo <= hi) {
138             int mid = (lo + hi) >> 1;
139             if(ok(mid)) hi = mid - 1;
140             else lo = mid + 1;
141         }
142         if(hi > n * m) puts("impossible");
143         else printf("%d
", hi);
144     }
145     return 0;
146 }
原文地址:https://www.cnblogs.com/kirai/p/6776319.html