人生有信仰 数据有梯度 暴力不爆零


bzoj 4439: [Swerc2015]Landscaping -- 最小割

4439: [Swerc2015]Landscaping

Time Limit: 2 Sec  Memory Limit: 512 MB

Description

FJ有一块N*M的矩形田地,有两种地形高地(用‘#’表示)和低地(用‘.’表示)
FJ需要对每一行田地从左到右完整开收割机走到头,再对每一列从上到下完整走到头,如下图所示
 
对于一个4*4的田地,FJ需要走8次。
收割机是要油的,每次从高地到低地或从低地到高地需要支付A的费用。
但是FJ有黑科技,可以高地与低地的互变,都只需要一个支付B的费用。
询问FJ需要支付最小费用。

 

Input

第一行包含四个整数N,M,A,B,意义如上文所述。
接下来是一个N*M的字符串矩阵,表示农田的地形,’#’表示高地,’.’表示低地。

 

Output

只包含一个正整数,表示最小费用。
1<=N,M<=50
1<=A,B<=100000

 

Sample Input

5 4 1000 2000
...#
#..#
...#
##..
###.

Sample Output

11000
样例解释:
把(2,1)的高地变成低地花费2000,燃料花费9000

HINT

我们以源点向高处,低处向汇点连权值为 B 的边,在相邻的点连权值为 A 的边,然后跑最小割

#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define N 100010
int n,m,S,T;
inline int pos(int i,int j){return (i-1)*m+j;}
char str[100];
int lj[N],to[N],v[N],fro[N],cnt=1;
void add(int a,int b,int c){fro[++cnt]=lj[a];to[cnt]=b;v[cnt]=c;lj[a]=cnt;}
void ins(int a,int b,int c){add(a,b,c);add(b,a,0);}
int q[N],dis[N],l,r;
bool bfs()
{
    int x;l=0;r=1;
    memset(dis,0,sizeof(dis));
    dis[S]=1;q[1]=S;
    while(l!=r)
    {
        x=q[l++];if(l==N) l=0;
        for(int i=lj[x];i;i=fro[i])
        {
            if(v[i]&&!dis[to[i]])
            {
                dis[to[i]]=dis[x]+1;
                if(to[i]==T) return 1;
                q[r++]=to[i];if(r==N) r=0;
            }
        }
    }
    return 0;
}
int dfs(int x,int p)
{
    if(x==T) return p;
    int tp,res=0;
    for(int i=lj[x];i;i=fro[i])
    {
        if(v[i]&&dis[to[i]]==dis[x]+1)
        {
            tp=dfs(to[i],min(p-res,v[i]));
            v[i]-=tp;v[i^1]+=tp;
            res+=tp;
            if(res==p) return p;
        }
    }
    if(res==0) dis[x]=0;
    return res;
}
int a,b,ans;
int main()
{
    scanf("%d%d%d%d",&n,&m,&a,&b);
    S=0;T=n*m+1;
    for(int i=1;i<=n;i++)
    {
        scanf("%s",str+1);
        for(int j=1;j<=m;j++)
        {
            if(str[j]=='#') ins(S,pos(i,j),b);
            else ins(pos(i,j),T,b);
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(i>1) ins(pos(i,j),pos(i-1,j),a);
            if(i<n) ins(pos(i,j),pos(i+1,j),a);
            if(j>1) ins(pos(i,j),pos(i,j-1),a);
            if(j<m) ins(pos(i,j),pos(i,j+1),a);
        }
    }
    while(bfs()) ans+=dfs(S,0x3f3f3f3f);
    printf("%d\n",ans);
    return 0;
}

 

posted @ 2017-08-05 14:31  lkhll  阅读(290)  评论(0编辑  收藏  举报