首先黑白染色 因为相邻的节点颜色必不同 相同颜色的节点之间没有关系(没有边)
然后Add(S,黑色点,A[i][j]) (黑色点,T,B[i][j])(S,白色点,B[i][j])(白色点,T,A[i][j])因为黑色点和白色点同属一个S/T才有额外贡献 所以这里A[i][j],B[i][j]要交换连
sum初始为矩阵里每个点的A,B之和 对于每个点 向它四周相邻的点连(u,v,C[i][j]+C[i'][j']) 注意这里黑色到白色 白色到黑色都要连 因为有属于S/T两种情况
然后一个点有X个相邻点则sum+=X*C[i][j] 因为上面连的C[i][j]+C[i'][j']容量的边其实有两条但是却不存在同时切两条的情况 最多只会切一条
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef int JQK; int n, m; namespace dinic { const int MAXN = 10050; const int MAXM = 100050; const int INF = 1000000050; int Head[MAXN], cur[MAXN], lev[MAXN], to[MAXM << 1], nxt[MAXM << 1], ed = 1; int S, T, MAXP; JQK f[MAXM << 1]; inline void addedge(int u, int v, JQK cap) { to[++ed] = v; nxt[ed] = Head[u]; Head[u] = ed; f[ed] = cap; to[++ed] = u; nxt[ed] = Head[v]; Head[v] = ed; f[ed] = 0; return; } inline bool BFS() { int u; for (int i = 0; i <= MAXP + 1; i++) { lev[i] = -1; } //memset(lev, -1, sizeof(lev)); queue<int>q; lev[S] = 0; q.push(S); while (q.size()) { u = q.front(); q.pop(); for (int i = Head[u]; i; i = nxt[i]) if (f[i] && lev[to[i]] == -1) { lev[to[i]] = lev[u] + 1; q.push(to[i]); /* if (to[i] == T) { return 1; } magic one way optimize */ } } for (int i = 0; i <= MAXP + 1; i++) { cur[i] = Head[i]; } //memcpy(cur, Head, sizeof Head); return lev[T] != -1; } JQK DFS(int u, JQK maxf) { if (u == T || !maxf) { return maxf; } JQK cnt = 0, tem; for (int &i = cur[u]; i; i = nxt[i]) if (f[i] && lev[to[i]] == lev[u] + 1) { tem = DFS(to[i], min(maxf, f[i])); maxf -= tem; f[i] -= tem; f[i ^ 1] += tem; cnt += tem; if (!maxf) { break; } } if (!cnt) { lev[u] = -1; } return cnt; } JQK Dinic() { JQK ans = 0; while (BFS()) { ans += DFS(S, INF); } return ans; } void init(int SS, int TT) { for (int i = 0; i <= MAXP + 1; i++) { Head[i] = 0; } ed = 1; S = SS; T = TT; return; } int work() { return Dinic(); } } int dir[4][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}}; int bl[105][105]; int sum = 0; int A[105][105], B[105][105], C[105][105]; int main() { int n, m; scanf("%d %d", &n, &m); dinic::MAXP = n * m + 5; int s, t; s = n * m + 1, t = s + 1; dinic::init(s, t); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { scanf("%d", &A[i][j]); sum += A[i][j]; } for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { scanf("%d", &B[i][j]); sum += B[i][j]; } for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { scanf("%d", &C[i][j]); } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { bl[i][j] = (i + j) % 2; int now = (i - 1) * m + j; if (bl[i][j]) { dinic::addedge(s, now, A[i][j]), dinic::addedge(now, t, B[i][j]); } else { dinic::addedge(s, now, B[i][j]), dinic::addedge(now, t, A[i][j]); } for (int k = 0; k < 4; k++) { int dx = i + dir[k][0]; int dy = j + dir[k][1]; if (dx >= 1 && dx <= n && dy >= 1 && dy <= m) { int aim = (dx - 1) * m + dy; sum += C[i][j]; dinic::addedge(now, aim, C[i][j] + C[dx][dy]); } } } } printf("%d\n", sum - dinic::Dinic()); return 0; }