bzoj1189: [HNOI2007]紧急疏散evacuate

看到黄学长的做法觉得有点疑问

网上搜了下发现确实有问题

看到PoPoQQQ大爷的啦 http://blog.csdn.net/popoqqq/article/details/41594921

然后怎么办呢

得把每个出口拆成很多个时刻 每个时刻到t建边

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<algorithm>
  5 #include<iostream>
  6 
  7 using namespace std;
  8 
  9 void setIO(const string& s) {
 10     freopen((s + ".in").c_str(), "r", stdin);
 11     freopen((s + ".out").c_str(), "w", stdout);
 12 }
 13 template<typename Q> Q read(Q& x) {
 14     static char c, f;
 15     for(f = 0; c = getchar(), !isdigit(c); ) if(c == '-') f = 1;
 16     for(x = 0; isdigit(c); c = getchar()) x = x * 10 + c - '0';
 17     if(f) x = -x;
 18     return x;
 19 }
 20 template<typename Q> Q read() {
 21     static Q x; read(x); return x;
 22 }
 23 
 24 // ISAP
 25 const int N = 40000 + 10, M = 500000 + 10, INF = ~0u >> 1;
 26 const int R = 400;
 27 
 28 struct Edge {
 29     int to, cap, adv;
 30     Edge *next;
 31     void init() {adv = cap;}
 32     Edge(int to = 0, int cap = 0, Edge *next = 0) : to(to), cap(cap), next(next) {}
 33 }pool[M * 2], *pis = pool, *fir[N], *pre[N];
 34 
 35 void AddEdge(int u, int v, int w) {
 36     fir[u] = new(pis++) Edge(v, w, fir[u]);
 37     fir[v] = new(pis++) Edge(u, 0, fir[v]);
 38 }
 39 
 40 Edge *inv(Edge *p) {
 41     return pool + ((p - pool) ^ 1);
 42 }
 43 
 44 namespace ISAP {
 45     int d[N], q[N], ql, qr;
 46     int n, s, t;
 47     int num[N];
 48     Edge *cur[N];
 49     
 50     void insert(int u, int dis) {
 51         if(d[u] == n) {
 52             d[u] = dis;
 53             q[qr++] = u;
 54         }
 55     }
 56     
 57     void BFS() {
 58         for(int u = 1; u <= n; u++) {
 59             d[u] = n;
 60         }
 61         insert(t, 0);
 62         while(ql ^ qr) {
 63             int u = q[ql++];
 64             for(Edge *p = fir[u]; p; p = p->next) if(inv(p)->adv){
 65                 insert(p->to, d[u] + 1);
 66             }
 67         }
 68     }
 69     
 70     int Augment() {
 71         int a = INF;
 72         for(int u = t; u != s; u = inv(pre[u])->to) {
 73             a = min(a, pre[u]->adv);
 74         }
 75         for(int u = t; u != s; u = inv(pre[u])->to) {
 76             pre[u]->adv -= a;
 77             inv(pre[u])->adv += a;
 78         }
 79         return a;
 80     }
 81     
 82     int Maxflow() {
 83         memset(num, 0, sizeof num);
 84         BFS();
 85         for(int u = 1; u <= n; u++) {
 86             cur[u] = fir[u];
 87             num[d[u]]++;
 88         }
 89         for(int i = 1; i < d[s]; i++) {
 90             if(!num[i]) return 0;
 91         }
 92         int flow = 0;
 93         for(int u = s; d[s] < n; ) {
 94             if(u == t) {
 95                 flow += Augment();
 96                 u = s;
 97             }
 98             int ok = 0;
 99             for(Edge *&p = cur[u]; p; p = p->next) if(p->adv) {
100                 int v = p->to;
101                 if(d[v] + 1 == d[u]) {
102                     pre[u = v] = p;
103                     ok = 1;
104                     break;
105                 }
106             }
107             if(!ok) {
108                 int &dis = d[u];
109                 if(!--num[dis]) break;
110                 dis = n;
111                 for(Edge *p = (cur[u] = fir[u]); p; p = p->next) if(p->adv) {
112                     dis = min(dis, d[p->to] + 1);
113                 }
114                 num[dis]++;
115                 if(u != s) u = inv(pre[u])->to;
116             }
117         }
118         return flow;
119     }
120     
121     int main(int _n, int _s, int _t) {
122         n = _n, s = _s, t = _t;
123         return Maxflow();
124     }
125 }
126 
127 const int maxn = 20 + 5;
128 
129 int n, m;
130 char g[maxn][maxn];
131 
132 int encode(int x, int y) {
133     return (x - 1) * m + y;
134 }
135 
136 void discode(int s, int& x, int& y) {
137     y = (s - 1) % m + 1;
138     x = (s - y) / m + 1;
139 }
140 
141 int mid;
142 
143 int q[maxn * maxn], ql, qr;
144 int d[maxn][maxn];
145 
146 void insert(int x, int y, int dis) {
147     if(d[x][y] > dis) {
148         d[x][y] = dis;
149         if(g[x][y] != 'D') q[qr++] = encode(x, y);
150     }
151 }
152 
153 const int dx[] = {0, 0, 1, -1};
154 const int dy[] = {1, -1, 0, 0};
155 
156 bool inmap(int x, int y) {
157     return 0 < x && x <= n && 0 < y && y <= m;
158 }
159 
160 int tot;
161 #include<vector>
162 vector<int> doors;
163 int ND[R][R];
164 Edge *rec[R][R];
165 
166 void BFS(int sx, int sy) {//(2, 2) -> (n - 1, n - 1)
167     memset(d, 0x3f, sizeof d);
168     ql = qr = 0;
169     insert(sx, sy, 0);
170     while(ql ^ qr) {
171         int s = q[ql++], x, y;
172         discode(s, x, y);
173         for(int k = 0; k < 4; k++) {
174             int xx = x + dx[k], yy = y + dy[k];
175             if(inmap(xx, yy) && g[xx][yy] != 'X') insert(xx, yy, d[x][y] + 1);
176         }
177     }
178 }
179 
180 void build(int s, int& cnt) {
181     for(int x0 = 2; x0 < n; x0++) {
182         for(int y0 = 2; y0 < m; y0++) if(g[x0][y0] == '.') {
183             ++cnt;
184             BFS(x0, y0); int u = encode(x0, y0);
185             AddEdge(s, u, 1);
186             for(unsigned i = 0; i < doors.size(); i++) {
187                 int v = doors[i], x, y; discode(v, x, y);
188                 if(d[x][y] < R) AddEdge(u, ND[v][d[x][y]], 1);
189             }
190         }
191     }
192 }
193 
194 void rebuild(int mid) {
195     for(Edge *p = pool; p != pis; (p++)->init());
196     for(unsigned i = 0; i < doors.size(); i++) {
197         int u = doors[i];
198         for(int j = mid + 1; j < R; j++) rec[u][j]->adv = 0;
199     }
200 }
201 
202 void find_doors(int t) {
203     for(int i = 1; i <= n; i++) {
204         for(int j = 1; j <= m; j += m - 1) {
205             if(g[i][j] == 'D') {
206                 doors.push_back(encode(i, j));
207             }
208         }
209     }
210     for(int j = 2; j < m; j++) {
211         for(int i = 1; i <= n; i += n - 1) {
212             if(g[i][j] == 'D') {
213                 doors.push_back(encode(i, j));
214             }
215         }
216     }
217     tot = n * m;
218     for(unsigned i = 0; i < doors.size(); i++) {
219         int u = doors[i];
220         for(int j = 1; j < R; j++) {
221             ND[u][j] = ++tot;
222             AddEdge(tot, t, 1);
223             rec[u][j] = pis - 2;
224             if(j > 1) AddEdge(tot - 1, tot, INF);
225         }
226     }
227 }
228 
229 int main() {
230 #ifdef DEBUG
231     freopen("in.txt", "r", stdin);
232     freopen("out.txt", "w", stdout);
233 #endif
234     
235     read(n), read(m);
236     for(int i = 1; i <= n; i++) {
237         scanf("%s", g[i] + 1);
238     }
239     
240     int s = 40000 + 1, t = 40000 + 2, cnt;
241     
242     find_doors(t);
243     build(s, cnt = 0);
244     int l = 0, r = R - 1, res = INF;
245     while(l <= r) {
246         int mid = (l + r) >> 1;
247         rebuild(mid);
248         int tmp = ISAP::main(t, s, t);
249         if(tmp >= cnt) r = mid - 1, res = mid;
250         else l = mid + 1;
251     }
252     if(res == INF) puts("impossible");
253     else printf("%d
", res);
254     
255     return 0;
256 }
原文地址:https://www.cnblogs.com/showson/p/5037190.html