传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2127
第3道最小割!!!分析我就不说了,网上到处都是。刷了三道最小割,终于更深刻的理解了根据不同方案的分析来确定边的流量233。。。
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define INF 0x3f3f3f3f const int maxn = 10010, maxm = 1000010, maxk = 110; int fir[maxn], edge[maxm], next[maxm], cap[maxm]; int d[maxn], vd[maxn]; int num[maxk][maxk]; int dd[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; int n, m, ans, s, t, cnt, tot; void addedge(int a, int b, int f) { edge[cnt] = b; next[cnt] = fir[a]; fir[a] = cnt; cap[cnt ++] = f; edge[cnt] = a; next[cnt] = fir[b]; fir[b] = cnt; cap[cnt ++] = 0; return; } int Isap(int r, int aflow) { if(r == t) return aflow; int flow = aflow, f, md = t - 1; for(int i = fir[r]; ~i ; i = next[i]) { int v = edge[i]; if(cap[i]) { if(d[r] == d[v] + 1) { f = min(flow, cap[i]); f = Isap(v, f); cap[i] -= f; cap[i ^ 1] += f; flow -= f; if(d[s] >= t) return aflow - flow; if(!flow) break; } md = min(md, d[v]); } } if(flow == aflow) { vd[d[r]] --; if(!vd[d[r]]) d[s] = t; d[r] = md + 1; vd[d[r]] ++; } return aflow - flow; } int main() { memset(fir, -1, sizeof(fir)); scanf("%d%d", &n, &m); for(int i = 1; i <= n; i ++) { for(int j = 1; j <= m; j ++) { num[i][j] = ++tot; } } s = tot + 1; t = tot + 2; int v; for(int i = 1; i <= n; i ++) { for(int j = 1; j <= m; j ++) { scanf("%d", &v); ans += v * 2; addedge(s, num[i][j], v * 2); } } for(int i = 1; i <= n; i ++) { for(int j = 1; j <= m; j ++) { scanf("%d", &v); ans += v * 2; addedge(num[i][j], t, v * 2); } } for(int i = 1; i < n; i ++) { for(int j = 1; j <= m; j ++) { scanf("%d", &v); ans += v * 2; addedge(s, num[i][j], v); addedge(s, num[i + 1][j], v); addedge(num[i][j], num[i + 1][j], v); addedge(num[i + 1][j], num[i][j], v); } } for(int i = 1; i < n; i ++) { for(int j = 1; j <= m; j ++) { scanf("%d", &v); ans += v * 2; addedge(num[i][j], t, v); addedge(num[i + 1][j], t, v); addedge(num[i][j], num[i + 1][j], v); addedge(num[i + 1][j], num[i][j], v); } } for(int i = 1; i <= n; i ++) { for(int j = 1; j < m; j ++) { scanf("%d", &v); ans += v * 2; addedge(s, num[i][j], v); addedge(s, num[i][j + 1], v); addedge(num[i][j], num[i][j + 1], v); addedge(num[i][j + 1], num[i][j], v); } } for(int i = 1; i <= n; i ++) { for(int j = 1; j < m; j ++) { scanf("%d", &v); ans += v * 2; addedge(num[i][j], t, v); addedge(num[i][j + 1], t, v); addedge(num[i][j], num[i][j + 1], v); addedge(num[i][j + 1], num[i][j], v); } } vd[0] = t; while(d[s] < t) ans -= Isap(s, INF); printf("%d\n", ans / 2); return 0; }