Minimum Cut Maximum Flow Theorem of UVA1515/Gym-100729F Pool Construction

This question can be thought of as "cut point" is really too strong Orz...

Mainly read Liu Rujia's Zishu 376 pages and blog https://blog.csdn.net/wang2147483647/article/details/54988598

To solve this problem, we have a deeper understanding of the concept of "cut", and suddenly we have a little understanding of the meaning of S, T sets and cut.

There are two points to be noted in this question:

1. The point capacity on the boundary is INF, which means that it is difficult to be "cut off". 2. The edge should be added between any two adjacent points, and the capacity is b.

After all kinds of things, I found that it was the size of the array. Complex mood. jpg

Generally, the number of edges is four times the number of points, and the number of points is even more square of the size of the matrix (the larger the better without MLE).

It's over at last. It's not easy. 55555. Attach AC code:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;

const int MAX=2500*4;
int n,m;
struct Edge
{
    int to, next, cap, flow;
}edge[MAX*4];
int tot,head[MAX];
int gap[MAX],dep[MAX],pre[MAX],cur[MAX];

void init()
{
    tot=0;
    memset(head,-1,sizeof(head));
}
void add(int u,int v,int w)
{
    edge[tot].to=v;edge[tot].cap=w;edge[tot].flow=0;
    edge[tot].next=head[u]; head[u]=tot++;
    edge[tot].to=u;edge[tot].cap=0;edge[tot].flow=0;
    edge[tot].next=head[v];head[v]=tot++;
}
int sap(int st,int en,int n)
{
    memset(gap,0,sizeof(gap));
    memset(dep,0,sizeof(dep));
    memcpy(cur,head,sizeof(head));
    int u=st;
    pre[u]=-1;
    gap[0]=n;
    int maxflow=0;
    while(dep[st]<n)
    {
        if(u==en)
        {
            int mindis=INF;
            for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
                if(mindis>edge[i].cap-edge[i].flow)
                    mindis=edge[i].cap-edge[i].flow;
            for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
            {
                edge[i].flow+=mindis;
                edge[i^1].flow-=mindis;
            }
            u=st;
            maxflow+=mindis;
            continue;
        }
        bool flag=false;
        int v;
        for(int i=cur[u];i!=-1;i=edge[i].next)
        {
            v=edge[i].to;
            if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u])
            {
                flag=true;
                cur[u]=pre[v]=i;
                u=v;
                break;
            }
        }
        if(flag)
        {
            u=v;
            continue;
        }
        else
        {
            int mindis=n;
            for(int i=head[u];i!=-1;i=edge[i].next)
                if(edge[i].cap-edge[i].flow&&dep[edge[i].to]<mindis)
                {
                    mindis=dep[edge[i].to];
                    cur[u]=i;
                }
            gap[dep[u]]--;
            if(gap[dep[u]]==0)
                break;
            dep[u]=mindis+1;
            gap[dep[u]]++;
            if(u!=st)
                u=edge[pre[u]^1].to;
        }
    }
    return maxflow;
}

inline int id(int i,int j)
{
    return (i-1)*m+j;
}
inline int in(int i,int j)
{
    return i>=1&&i<=n&&j>=1&&j<=m;
}
int main()
{
    int t;
    scanf("%d",&t);
    int d,f,b;
    char ss[55][55];
    while(t--)
    {
        scanf("%d%d",&m,&n);
        scanf("%d%d%d",&d,&f,&b);
        //memset(ss,0,sizeof(ss));
        for(int i=1;i<=n;i++)
            scanf("%s",ss[i]+1);
        int ans=0;
        int s=n*m+1,t=n*m+2;
        memset(edge,0,sizeof(edge));
        init();
        for(int i=1;i<=n;i++)
        {
            if(ss[i][1]=='.')
            {
                ss[i][1]='#';
                ans+=f;
            }
            if(ss[i][m]=='.')
            {
                ss[i][m]='#';
                ans+=f;
            }
        }
        for(int j=2;j<m;j++)
        {
            if(ss[1][j]=='.')
            {
                ss[1][j]='#';
                ans+=f;
            }
            if(ss[n][j]=='.')
            {
                ss[n][j]='#';
                ans+=f;
            }
        }
        //cout<<"ans="<<ans<<endl;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                int iid=id(i,j);
                if(ss[i][j]=='#')
                {
                    if(i==1||i==n||j==1||j==m)
                        add(s,iid,INF);
                    else
                        add(s,iid,d);
                }
                else if(ss[i][j]=='.')
                    add(iid,t,f);
                if(in(i-1,j))
                    add(iid,id(i-1,j),b);
                if(in(i+1,j))
                    add(iid,id(i+1,j),b);
                if(in(i,j-1))
                    add(iid,id(i,j-1),b);
                if(in(i,j+1))
                    add(iid,id(i,j+1),b);
            }
        printf("%d\n",ans+sap(s,t,n*m+2));
    }
    return 0;
}

 

Posted by twilson on Sun, 03 Feb 2019 18:03:16 -0800