私はBZOJの波を最初から最後まで乾燥することを決めました!
あなたはそれを停止するいくつかの質問を書きますが、まだ新しい姿勢の友人を勉強したいことができませんでした。
【BeiJing2006]ウルフキャッチウサギ
シークすなわち \((1、1)\)する((N、M)\ \ ) 最小カット。実行するためにDinic。
コード
#include <bits/stdc++.h>
using namespace std;
inline int read() {
int x = 0, f = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
return x * f;
}
const int N = 1e6 + 10;
const int INF = 0x3f3f3f3f;
struct E { int v, ne, f; } e[N * 7];
int head[N], cnt, n, m, iter[N], level[N];
inline void add(int u, int v, int f) {
e[cnt].v = v; e[cnt].f = f; e[cnt].ne = head[u]; head[u] = cnt++;
e[cnt].v = u; e[cnt].f = f; e[cnt].ne = head[v]; head[v] = cnt++;
}
bool bfs(int s, int t) {
for (int i = 0; i <= t; i++) level[i] = -1, iter[i] = head[i];
queue<int> que;
que.push(s);
level[s] = 0;
while (!que.empty()) {
int u = que.front(); que.pop();
for (int i = head[u]; ~i; i = e[i].ne) {
int v = e[i].v, f = e[i].f;
if (level[v] < 0 && f) {
level[v] = level[u] + 1;
que.push(v);
}
}
}
return level[t] != -1;
}
int dfs(int u, int t, int f) {
if (u == t || !f) return f;
int flow = 0;
for (int i = iter[u]; ~i; i = e[i].ne) {
iter[u] = i;
int v = e[i].v;
if (level[v] == level[u] + 1 && e[i].f) {
int w = dfs(v, t, min(f, e[i].f));
if (!w) continue;
e[i].f -= w, e[i^1].f += w;
flow += w, f -= w;
if (f <= 0) break;
}
}
return flow;
}
int main() {
memset(head, -1, sizeof(head));
n = read(), m = read();
for (int i = 1; i <= n; i++) {
for (int j = 1; j < m; j++) {
int f = read();
add((i - 1) * m + j, (i - 1) * m + j + 1, f);
}
}
for (int i = 1; i < n; i++) {
for (int j = 1; j <= m; j++) {
int f = read();
add((i - 1) * m + j, i * m + j, f);
}
}
for (int i = 1; i < n; i++) {
for (int j = 1; j < m; j++) {
int f = read();
add((i - 1) * m + j, i * m + j + 1, f);
}
}
int ans = 0;
int s = 1, t = n * m;
for (; bfs(s, t); ans += dfs(s, t, INF));
printf("%d\n", ans);
return 0;
}