GYM 101128 F.Landscaping [Minimum Cut--I don't understand yet]

The main idea of ​​the title: give you an N*M matrix, where "#" represents highland, "." represents lowland, we have N+M vehicles, and it takes A to go from highland to lowland, we make highland into lowland or The cost of making a lowland into a highland is B. Our car travels from top to bottom in each column and from left to right in each row. Ask what is the minimum cost.

In fact, I don't understand other people's solutions, and neither do I, so I'll put it here first.

Idea:
Obviously we can't Dp directly, because if our current block changes, it will affect many previous results. We consider adding more dimensions to cancel this after-effect and it is fruitless. We might as well consider network flow.
We ask for the minimum cost, and it is not difficult to think of the minimum cut, so consider building a map.
① First of all, we can divide the points into two categories, so that we make the low ground into one category, and the rest into one category, then a bipartite graph is formed.
We connect the source point to each low point, the flow is B, and then we connect each high point to the sink, and the flow is also B.
② Then we connect each adjacent point, and the flow is A.
This way We only have a cost if there are both high and low ground (there is flow from source to sink.).
After building the map, you can run the maximum flow.

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
struct node
{
    int from;
    int to;
    int w;
    int next;
}e[100*65*4];
char a[55][55];
int cur[8500];
int head[8500];
int divv[8500];
int fx[4]={1,0,-1,0};
int fy[4]={0,1,0,-1};
int n,m,A,B;
int cont,ss,tt;
void add(int from,int to,int w)
{
    e[cont].from=from;
    e[cont].w=w;
    e[cont].to=to;
    e[cont].next=head[from];
    head[from]=cont++;
}
int num(int x,int y)
{
    return 1+m*x+y;
}
void Get_map()
{
    cont=0;
    memset(head,-1,sizeof(head));
    ss=n*m+1;tt=ss+1;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            if(a[i][j]=='.')
            {
                add(ss,num(i,j),B);
                add(num(i,j),ss,0);
            }
            else
            {
                add(num(i,j),tt,B);
                add(tt,num(i,j),0);
            }
            for(int k=0;k<4;k++)
            {
                int xx=fx[k]+i;
                int yy=fy[k]+j;
                if(xx>=0&&xx<n&&yy>=0&&yy<m)
                {
                    add(num(i,j),num(xx,yy),A);
                    add(num(xx,yy),num(i,j),0);
                }
            }
        }
    }
}
int makedivv()
{
    memset(divv,0,sizeof(divv));
    divv[ss]=1;
    queue<int >s;
    s.push(ss);
    while(!s.empty())
    {
        int u=s.front();
        if(u==tt)return 1;
        s.pop();
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int w=e[i].w;
            int v=e[i].to;
            if(divv[v]==0&&w)
            {
                divv[v]=divv[u]+1;
                s.push(v);
            }
        }
    }
    return 0;
}
int Dfs(int u,int maxflow,int tt)
{
    if(u==tt)return maxflow;
    int ret=0;
    for(int &i=cur[u];i!=-1;i=e[i].next)
    {
        int v=e[i].to;
        int w=e[i].w;
        if(divv[v]==divv[u]+1&&w)
        {
            int f=Dfs(v,min(maxflow-ret,w),tt);
            e[i].w-=f;
            e[i^1].w+=f;
            ret+=f;
            if(ret==maxflow)return ret;
        }
    }
    return ret;
}
void Dinic()
{
    int ans=0;
    while(makedivv()==1)
    {
        memcpy(cur,head,sizeof(head));
        ans+=Dfs(ss,0x3f3f3f3f,tt);
    }
    printf("%d\n",ans);
}
int main()
{
    while(~scanf("%d%d%d%d",&n,&m,&A,&B))
    {
        for(int i=0;i<n;i++)scanf("%s",a[i]);
        Get_map();
        Dinic();
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325059092&siteId=291194637