BZOJ 1001. [BeiJing2006]狼抓兔子
做法一:直接dinic跑
做法二:平面图最小割转对偶图最短路,左下外区域为起点,右上外区域为终点,一条边连接两个区域,把区域看成点,就变成了最短路问题。
#include <bits/stdc++.h> namespace IO { char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh = '\n'; int p, p3 = -1; void read() {} void print() {} inline int getc() { return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; } inline void flush() { fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; } template <typename T, typename... T2> inline void read(T &x, T2 &... oth) { T f = 1; x = 0; char ch = getc(); while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getc(); } while (isdigit(ch)) { x = x * 10 + ch - 48; ch = getc(); } x *= f; read(oth...); } template <typename T, typename... T2> inline void print(T x, T2... oth) { if (p3 > 1 << 20) flush(); if (x < 0) buf2[++p3] = 45, x = -x; do { a[++p] = x % 10 + 48; } while (x /= 10); do { buf2[++p3] = a[p]; } while (--p); buf2[++p3] = hh; print(oth...); } } const int N = 2e6 + 7, M = 6e6 + 7; const int INF = 0x3f3f3f3f; struct E { int v, ne, c; } e[M]; int head[N], cnt = 1, n, m, id[1007][1007][2], tol; int dis[N]; inline void add(int u, int v, int c) { e[++cnt].v = v; e[cnt].ne = head[u]; e[cnt].c = c; head[u] = cnt; std::swap(u, v); e[++cnt].v = v; e[cnt].ne = head[u]; e[cnt].c = c; head[u] = cnt; } #define pii pair<int, int> #define fi first #define se second bool done[N]; int dijkstra(int s, int t) { for (int i = 1; i <= tol; i++) dis[i] = INF; dis[s] = 0; std::priority_queue< std::pii, std::vector<std::pii>, std::greater<std::pii> > que; que.push(std::pii(0, s)); while (!que.empty()) { std::pii p = que.top(); que.pop(); int u = p.se; if (u == t) break; if (done[u]) continue; done[u] = 1; for (int i = head[u]; i; i = e[i].ne) { int v = e[i].v; if (dis[v] > dis[u] + e[i].c) { dis[v] = dis[u] + e[i].c; que.push(std::pii(dis[v], v)); } } } return dis[t]; } int main() { IO::read(n, m); int s = 1, t = 2; tol = 2; for (int i = 1; i < n; i++) for (int j = 1; j < m; j++) id[i][j][0] = ++tol, id[i][j][1] = ++tol; for (int i = 1; i <= n; i++) for (int j = 1; j < m; j++) { int u, v; if (i == n) u = s; else u = id[i][j][1]; if (i == 1) v = t; else v = id[i - 1][j][0]; int c; IO::read(c); add(u, v, c); } for (int i = 1; i < n; i++) for (int j = 1; j <= m; j++) { int u, v; if (j == 1) u = s; else u = id[i][j - 1][1]; if (j == m) v = t; else v = id[i][j][0]; int c; IO::read(c); add(u, v, c); } for (int i = 1; i < n; i++) for (int j = 1; j < m; j++) { int u = id[i][j][0], v = id[i][j][1]; int c; IO::read(c); add(u, v, c); } printf("%d\n", dijkstra(s, t)); return 0; }