BZOJ3894/LuoguP4313 文理分科 (最小割)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define R(a,b,c) for(register int  a = (b); a <= (c); ++ a)
#define nR(a,b,c) for(register int  a = (b); a >= (c); -- a)
#define Max(a,b) ((a) > (b) ? (a) : (b))
#define Min(a,b) ((a) < (b) ? (a) : (b))
#define Fill(a,b) memset(a, b, sizeof(a))
#define Swap(a,b) a^=b^=a^=b
#define ll long long
#define ON_DEBUG

#ifdef ON_DEBUG

#define D_e_Line printf("\n\n----------\n\n")
#define D_e(x)  cout << #x << " = " << x << endl
#define Pause() system("pause")

#else

#define D_e_Line ;

#endif

struct ios{
    template<typename ATP>ios& operator >> (ATP &x){
        x = 0; int f = 1; char c;
        for(c = getchar(); c < '0' || c > '9'; c = getchar()) if(c == '-')  f = -1;
        while(c >= '0' && c <= '9') x = x * 10 + (c ^ '0'), c = getchar();
        x*= f;
        return *this;
    }
}io;
using namespace std;

const int N = 30007;
const int M = 300007;

int S, T;
int n, m;

struct Edge{
	int nxt, pre, w;
}e[M];
int head[N], cntEdge = 1; // why 1, why not 0 ? because of S ?
inline void add(int u, int v, int w){
	e[++cntEdge] = (Edge){head[u], v, w}, head[u] = cntEdge;
}
inline void Add(int u, int v, int w){
	add(u, v, w);
	add(v, u, 0);
}

int q[N],h[N];
inline bool BFS(){
    int t = 0, w = 1;
    Fill(h, -1);
    h[S] = 0, q[0] = S;
    while(t != w){
        int u = q[t++];
        for(register int i = head[u]; i; i =e[i].nxt){
            int v = e[i].pre;
            if(e[i].w && h[v] == -1){
                h[v] = h[u] + 1;
                q[w++] = e[i].pre;
            }
        }
    }
    return h[T] != -1;
}
inline int DFS(int u, int f){
    if(u == T) return f;
    int w, used = 0;
    for(register int i = head[u]; i; i = e[i].nxt){
        int v = e[i].pre;
        if(h[v] == h[u] + 1){
            w = DFS(v, Min(f - used, e[i].w));
            e[i].w -= w, e[i^1].w += w;
            used += w;
            if(used == f) return f;
        }
    }
    if(!used) h[u] = -1;
    return used;
}
inline int Dinic(){
    int sum = 0;
    while(BFS()){
        sum += DFS(S, 0x7fffffff);
    }
    return sum;
}


int dx[5] = {-1, 1, 0, 0, 0}, dy[5] = {0, 0, -1, 1, 0}; // (0, 0) is also useful in this problem
inline int id(int x, int y){
	return (x - 1) * m + y;
}
inline void Connect(int x, int y){
	R(i, 0, 4){
		int fx = x + dx[i], fy = y + dy[i];
		if(fx < 1 || fy < 1 || fx > n || fy >m) continue;
		Add(n * m + id(fx, fy), id(x, y), 0x3f3f3f3f);
		Add(id(x, y), n * m * 2 + id(fx, fy), 0x3f3f3f3f);
	}
}

int main(){
	io >> n >> m;
	T = n * m *3 + 1;
	long long sum = 0;
	int val;
	R(i,1,n){
		R(j,1,m){
			io >> val;
			Add(S, id(i, j), val);
			sum += val;
		}
	}
	R(i,1,n){
		R(j,1,m){
			io >> val;
			Add(id(i, j), T, val);
			sum += val;
		}
	}
	R(i,1,n){
		R(j,1,m){
			io >> val;
			Add(S, n * m + id(i, j), val);
			sum += val;
		}
	}
	
	R(i,1,n){
		R(j,1,m){
			io >> val;
			Add(n * m * 2 + id(i, j), T, val);
			sum += val;
		}
	}
	R(i,1,n){
		R(j,1,m){
			Connect(i, j);
		}
	}
	
	printf("%lld", sum - Dinic());
	
	return 0;
}

posted @ 2019-07-17 20:53  邱涵的秘密基地  阅读(123)  评论(0编辑  收藏  举报