标签:
题意很明显就是求最小割了,根据最小割最大流定理,数值等价于求最大流。
上模板。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int MAXN = 1000010;//点数的最大值 const int MAXM = 6000060;//边数的最大值 const int INF = 0x3f3f3f3f; struct Dinic { int n, m, T, e, first[MAXN], next[MAXM], u[MAXM], v[MAXM], flow[MAXM]; int q[MAXN], d[MAXN], work[MAXN], s[MAXN]; void add(int a, int b, int f) { u[e] = a; v[e] = b; flow[e] = f; next[e] = first[a]; first[a] = e; e ++; } void init(int n,int m) { this->n=n; this->m=m; T = n * m - 1; e = 0; for(i = 0; i <= T; i ++) first[i] = -1; } int bfs() { int i, j, rear; for(i = 1; i <= T; i ++) d[i] = -1; d[0] = 0; rear = 0; q[rear ++] = 0; for(i = 0; i < rear ; i ++) for(j = first[q[i]]; j != -1; j = next[j]) if(flow[j] && d[v[j]] == -1) { d[v[j]] = d[q[i]] + 1; if(v[j] == T) return 1; q[rear ++] = v[j]; } return 0; } int dinic() { int i, j, cur, r, res = 0; while(bfs()) { r = 0; cur = 0; for(i = 0; i <= T; i ++) work[i] = first[i]; for(;;) { if(cur == T) { int a = INF, minr = r; for(i = 0; i < r; i ++) if(flow[s[i]] < a) { a = flow[s[i]]; minr = i; } for(i = 0; i < r; i ++) { flow[s[i]] -= a; flow[s[i] ^ 1] += a; } r = minr; cur = u[s[r]]; res += a; } for(i = work[cur]; i != -1; i = next[i]) if(flow[i] && d[v[i]] == d[cur] + 1) break; work[cur] = i; if(i != -1) { s[r ++] = i; cur = v[i]; } else { d[cur] = -1; if(r == 0) break; r --; cur = u[s[r]]; } } } return res; } }; Dinic dinic; int main() { int n,m; while(scanf("%d%d", &n, &m) == 2) { dinic.init(n,m); int x; for(int i=0; i<n; ++i) { for(int j=0; j<m-1; ++j) { scanf("%d",&x); dinic.add(i*m+j,i*m+j+1,x); dinic.add(i*m+j+1,i*m+j,x); } } for(int i=0; i<n-1; ++i) { for(int j=0; j<m; ++j) { scanf("%d",&x); dinic.add(i*m+j,(i+1)*m+j,x); dinic.add((i+1)*m+j,i*m+j,x); } } for(int i=0; i<n-1; ++i) { for(int j=0; j<m-1; ++j) { scanf("%d",&x); dinic.add(i*m+j,(i+1)*m+j+1,x); dinic.add((i+1)*m+j+1,i*m+j,x); } } printf("%d\n", dinic.dinic()); } return 0; }
标签:
原文地址:http://www.cnblogs.com/rockzh/p/4640489.html