# [SMOJ2207]方格取数问题

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>

using namespace std;

const int MAXM = 100;
const int MAXN = 100;
const int dx[] = {-1, 1, 0, 0};
const int dy[] = {0, 0, -1, 1};
const int INF = 0x3f3f3f3f;

struct Edge {
Edge *next;
int cap;
int dest;
} edges[MAXM * MAXN << 1], *current, *first_edge[MAXM * MAXN];

int m, n, s, t;
bool vis[MAXM * MAXN];

inline int pos(int x, int y) { return x * n + y; } //根据行列分配唯一的顶点编号

Edge *counterpart(Edge *x) {
return edges + ((x - edges) ^ 1);
}

void insert(int u, int v, int c) {
current -> next = first_edge[u];
current -> cap = c;
current -> dest = v;
first_edge[u] = current ++;
}

int dfs(int u, int f) {
if (u == t) return f;
if (vis[u]) return 0; else vis[u] = true;
for (Edge *p = first_edge[u]; p; p = p -> next)
if (p -> cap)
if (int res = dfs(p -> dest, min(f, p -> cap))) {
p -> cap -= res;
counterpart(p) -> cap += res;
return res;
}
return 0;
}

int main(void) {
freopen("2207.in", "r", stdin);
freopen("2207.out", "w", stdout);
scanf("%d%d", &m, &n); current = edges;
s = 0; t = m * n + 1; int ans = 0;
fill(first_edge, first_edge + t + 1, (Edge*)0);
for (int i = 0; i < m; i++)
for (int j = 1; j <= n; j++) {
int num; scanf("%d", &num); ans += num;
if ((i + j) & 1) { //黑
insert(s, pos(i, j), num); insert(pos(i, j), s, 0);
for (int k = 0; k < 4; k++) {
int nx = i + dx[k], ny = j + dy[k];
if (nx >= 0 && nx < m && ny > 0 && ny <= n) insert(pos(i, j), pos(nx, ny), INF), insert(pos(nx, ny), pos(i, j), 0);
}
} else insert(pos(i, j), t, num), insert(t, pos(i, j), 0); //白
}
while (true) {
memset(vis, false, sizeof vis);
if (int res = dfs(s, INF)) ans -= res; else break;
}
printf("%d\n", ans);
return 0;
}

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120