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;
}

猜你喜欢

转载自www.cnblogs.com/bingoyes/p/11203597.html