BZOJ3894: Arts and science branch

Continue to fill the hole

Classical minimum cut

For each point, three points a,b,c represent whether the surrounding is full text, whether the point is full text, and whether the surrounding is full text
Add all values first
Then b of each point and a and C of the four surrounding points have the binary relation of the minimum cut. What's the edge building? Turn to a model of the minimum cut. The value and the minimum cut are the maximum value

Where Jianbian is, the S company of the source point and the T company of the sink point represent the selection
So the connection (S,b, the cost of selection), (b,T, the cost of selection), (S,a,0), (a,T, the cost of surrounding full text). The connection of point c is opposite to point a

Then for binary relations, such as b and a of an adjacent point, we can't select this point. Then a is the full text, so it connects a side (b,a,inf). b and c are similar

And then it's like it's done

code:

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define inf 1e9
using namespace std;

const int dx[] = {0,-1,0,1,0};
const int dy[] = {0,0,1,0,-1};
const int maxn = 310000;
const int maxm = maxn<<2;

int n,m,st,ed;
struct edge{int y,c,nex;}a[maxm]; int len,fir[maxn],fi[maxn];
inline void ins(const int x,const int y,const int c)
{
    a[++len]=(edge){y,c,fir[x]};fir[x]=len;
    a[++len]=(edge){x,0,fir[y]};fir[y]=len;
}

int h[maxn];
queue<int>q;
bool bfs()
{
    for(int i=1;i<=ed;i++) h[i]=0;
    h[st]=1; q.push(st);
    while(!q.empty())
    {
        const int x=q.front(); q.pop();
        for(int k=fir[x],y=a[k].y;k;k=a[k].nex,y=a[k].y) if(a[k].c&&!h[y])
            h[y]=h[x]+1,q.push(y);
    }
    return h[ed]>0;
}
int dfs(int x,int flow)
{
    if(x==ed) return flow;
    int delta=0;
    for(int &k=fi[x],y=a[k].y;k;k=a[k].nex,y=a[k].y)
    {
        if(a[k].c&&h[y]==h[x]+1)
        {
            int minc=dfs(y,min(a[k].c,flow-delta));
            a[k].c-=minc,a[k^1].c+=minc;
            delta+=minc;
        }
        if(delta==flow) return delta;
    }
    return delta;
}
int Flow()
{
    int re=0;
    while(bfs()) 
    {
        for(int i=1;i<=ed;i++) fi[i]=fir[i];
        re+=dfs(st,INT_MAX);
    }
    return re;
}
int ans;

int main()
{
    len=1;

    scanf("%d%d",&n,&m); int N=n*m; st=N*3+1,ed=st+1;
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
    {
        int id=(i-1)*m+j;
        int x; scanf("%d",&x);
        ins(st,id,x); ans+=x;
    }
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
    {
        int id=(i-1)*m+j;
        int x; scanf("%d",&x);
        ins(id,ed,x); ans+=x;
    }
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
    {
        int id=(i-1)*m+j;
        int x; scanf("%d",&x);
        ins(st,id+N,x),ans+=x;
    }
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
    {
        int id=(i-1)*m+j;
        int x; scanf("%d",&x);
        ins(id+2*N,ed,x),ans+=x;
    }

    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
    {
        int idx=(i-1)*m+j;
        for(int k=0;k<5;k++)
        {
            int x=i+dx[k],y=j+dy[k];
            if(x&&y&&x<=n&&y<=m)
            {
                int idy=(x-1)*m+y;
                ins(idx+N,idy,inf);
                ins(idy,idx+2*N,inf);
            }
        }
    }
    printf("%d\n",ans-Flow());

    return 0;
}

Posted by gmcalp on Fri, 03 Apr 2020 16:12:52 -0700