题目地址:P4001 [ICPC-Beijing 2006]狼抓兔子
平面图
边与边只在顶点相交的图。
对偶图
对于一个平面图,都有其对应的对偶图。
- 平面图被划分出的每一个区域当作对偶图的一个点;
- 平面图中的每一条边两边的区域对应的点用边相连,特别地,若两边为同一区域则加一条回边(自环)。
这样构成的图即为原平面图的对偶图。
定理
平面图最小割 \(=\) 对偶图最短路。
#include <bits/stdc++.h>
#define pii pair<int, int>
#define X first
#define Y second
#define mp make_pair
#define ui unsigned int
using namespace std;
const int N = 2e6 + 6;
int n, m, s, t, d[N];
vector<pii> e[N];
priority_queue<pii> q;
bitset<N> v;
inline void add(int x, int y, int z) {
e[x].push_back(mp(y, z));
}
inline int get(int i, int j, int k) {
return 2 * (m - 1) * (i - 1) + 2 * (j - 1) + k;
}
inline void ins(int x, int y) {
int z;
scanf("%d", &z);
add(x, y, z);
add(y, x, z);
}
inline void dijkstra() {
memset(d, 0x3f, sizeof(d));
d[s] = 0;
q.push(mp(0, s));
while (q.size()) {
int x = q.top().Y;
if (x == t) return;
q.pop();
if (v[x]) continue;
v[x] = 1;
for (ui i = 0; i < e[x].size(); i++) {
int y = e[x][i].X, z = e[x][i].Y;
if (d[y] > d[x] + z) {
d[y] = d[x] + z;
q.push(mp(-d[y], y));
}
}
}
}
int main() {
cin >> n >> m;
t = 2 * (n - 1) * (m - 1) + 1;
for (int j = 1; j < m; j++) ins(get(1, j, 2), t);
for (int i = 2; i < n; i++)
for (int j = 1; j < m; j++)
ins(get(i - 1, j, 1), get(i, j, 2));
for (int j = 1; j < m; j++) ins(get(n - 1, j, 1), s);
for (int i = 1; i < n; i++) {
ins(get(i, 1, 1), s);
for (int j = 2; j < m; j++)
ins(get(i, j - 1, 2), get(i, j, 1));
ins(get(i, m - 1, 2), t);
}
for (int i = 1; i < n; i++)
for (int j = 1; j < m; j++)
ins(get(i, j, 1), get(i, j, 2));
dijkstra();
cout << d[t] << endl;
return 0;
}