题解 P6094 【[JSOI2015]圈地】

· · 题解

原题链接:P6094 [JSOI2015]圈地

题意简述

思路与解答

Code

#include <cstdio>
#include <queue>
#include <iostream>
#include <cstring>
#define abs(x) (x<0?-x:x)

using namespace std;

const int MAXN = 80010;
const int INF = 0x3f3f3f3f; 

int n, m;

inline int id(int i, int j){return (i-1)*m+j;}

struct edge{
    int ne, to, fl;
    edge(int N=0,int T=0,int F=0):ne(N),to(T),fl(F){}
}e[MAXN*6];
int fir[MAXN], num = 1;
int s, t;
inline void adde(int a, int b, int c)
{
    e[++num] = edge(fir[a], b, c);
    fir[a] = num;
}
inline void join(int a, int b, int c)
{
    adde(a, b, c);
    adde(b, a, 0);
}

int dep[MAXN], cur[MAXN];
queue<int> q;
bool bfs(int s, int t)
{
    for(int i=0;i<=n*m+1;i++)
        dep[i] = 0, cur[i] = fir[i];
    while(!q.empty()) q.pop();
    q.push(s);
    dep[s] = 1;
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        for(int i=fir[u];i;i=e[i].ne)
        {
            int v = e[i].to;
            if(dep[v] || !e[i].fl) continue;
            dep[v] = dep[u] + 1;
            q.push(v);
        }
    }
    return dep[t];
}
int dfs(int u, int fln)
{
    if(u == t) return fln;
    int res = 0;
    for(int& i=cur[u];i;i=e[i].ne)
    {
        int v = e[i].to;
        if(!e[i].fl || dep[v] != dep[u]+1) continue;
        int sum = dfs(v, min(fln, e[i].fl));
        e[i].fl -= sum;
        e[i^1].fl += sum;
        fln -= sum;
        res += sum;
        if(!fln) break;
    }
    if(!res) dep[u] = 0;
    return res;
}
inline int dinic()
{
    int res = 0;
    while(bfs(s, t)) res += dfs(s, INF);
    return res;
}

int main()
{
    scanf("%d%d",&n,&m);
    s = 0; t = n*m+1;
    int sum = 0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            int a;
            scanf("%d",&a);
            if(a > 0) join(s, id(i, j), a);
            if(a < 0) join(id(i, j), t, -a);
            sum += abs(a);
        }
    }
    for(int i=1;i<n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            int a;
            scanf("%d",&a);
            join(id(i, j), id(i+1, j), a);
            join(id(i+1, j), id(i, j), a);
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<m;j++)
        {
            int a;
            scanf("%d",&a);
            join(id(i, j), id(i, j+1), a);
            join(id(i, j+1), id(i, j), a);
        }
    }
    printf("%d\n",sum-dinic());
    return 0;
}