看到黄学长的做法觉得有点疑问
网上搜了下发现确实有问题
看到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 }