UVALive 5905 Pool Construction 最小割,s-t割性质 难度:3

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3916

这道题要求一种填充+挖坑+建屏障的方法,使得这块土地上的所有坑和草地之间都有屏障,挖坑花费d每块,填充花费f每块,建屏障花费b每两块之间,注意并不要求一定有坑,但是外围一圈要一定没有坑,所以需要预先填充好

令st代表平地,ed代表坑,边权为花费,那么本题是要求一个st-ed最小割,因为s到平地花费为0,所以不建边,同理坑到ed也不需要花费不建边,每个点到相邻点建边,容量为b,s到坑建边,容量为d,平地到e建边,容量为f,为了防止外围的平地被挖,容量设为inf.

以st为起点,ed为终点,求一遍最大流,即最小割即可
这道题一开始会以为是dp,其实是一道最小割,虽然有2500个点,50000条边左右,但是仍然可以用网络流跑过,一开始想不出怎么处理屏障,但是其实只需要把每个点和相邻点之间都连起来即可,横向的流量没有意义,也就是说只有平地和坑之间的边会限制流量.

#include <cstdio>

#include <cstring>

#include <algorithm>

using namespace std;

const int maxn=5000;

const int maxm=5000000;

const int inf=0x3fffffff;

int first[maxn];

struct edge{

        int nxt,from,t,f,c;

}e[maxm];

int w,h,d,fl,b,len;

char maz[60][60];

const int dx[4]={1,-1,0,0};

const int dy[4]={0,0,1,-1};

int st,ed,num;



int dis[maxn],gap[maxn];

bool in(int x,int y){return x>=0&&x<h&&y>=0&&y<w;}

void addedge(int from,int t,int c){

        e[len].nxt=first[from];

        e[len].from=from;

        e[len].t=t;

        e[len].f=c;

        e[len].c=c;

        first[from]=len++;

        swap(from,t);c=0;



        e[len].nxt=first[from];

        e[len].from=from;

        e[len].t=t;

        e[len].f=c;

        e[len].c=c;

        first[from]=len++;

}

int dfs(int s,int flow){

        if(s==ed)return flow;

        int mindis=num-1;

        int tflow=flow,sub;

        for(int p=first[s];p!=-1;p=e[p].nxt){

                int t=e[p].t;

                if(e[p].f>0){

                        if(dis[t]+1==dis[s]){

                                sub=dfs(t,min(tflow,e[p].f));

                                e[p].f-=sub;e[p^1].f+=sub;

                                tflow-=sub;

                                if(dis[st]>=ed)return flow-tflow;

                                if(tflow<=0)break;

                        }

                        mindis=min(mindis,dis[t]);

                }

        }

        if(flow-tflow<=0){

                --gap[dis[s]];

                if(gap[dis[s]]==0)dis[st]=ed;

                else {

                        dis[s]=mindis+1;

                        ++gap[dis[s]];

                }

        }

        return flow-tflow;

}



int maxflow(){

        int flow=0;

        gap[0]=num;

        while(dis[st]<ed){

                flow+=dfs(st,inf);

        }

        return flow;

}

void init(){

        len=0;

        st=w*h;

        ed=st+1;

        num=st+2;

        fill(first,first+num,-1);

        fill(gap,gap+num,0);

        fill(dis,dis+num,0);

}

int main(){

        int T;

        scanf("%d",&T);

        while(T--){

                scanf("%d%d%d%d%d",&w,&h,&d,&fl,&b);

                init();

                int ans=0;

                for(int i=0;i<h;i++)scanf("%s",maz[i]);



                for(int i=0;i<h;i++){

                        for(int j=0;j<w;j++){

                                for(int k=0;k<4;k++){

                                        int tx=i+dx[k],ty=j+dy[k];

                                        if(in(tx,ty)){

                                                addedge(i*w+j,tx*w+ty,b);

                                        }

                                }

                                if(maz[i][j]=='#'){

                                        if(i==0||i==h-1||j==0||j==w-1){

                                               addedge(i*w+j,ed,inf);

                                        }

                                        else {

                                                addedge(i*w+j,ed,d);

                                        }

                                }

                                else {

                                        if(i==0||i==h-1||j==0||j==w-1){

                                               ans+=fl;

                                                maz[i][j]='#';

                                               addedge(i*w+j,ed,inf);

                                        }

                                        else {

                                               addedge(st,i*w+j,fl);

                                        }

                                }

                        }

                }

                ans+=maxflow();

                printf("%d\n",ans);

        }

        return 0;

}

  

你可能感兴趣的:(struct)