zoukankan      html  css  js  c++  java
  • UVa1515 Pool construction(最小割)

    题目

    Source

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4261

    Description

    You are working for the International Company for Pool Construction, a construction company which specializes in building swimming pools. A new client wants to build several new pool areas. A pool area is a rectangular grid of w × h square patches, consisting of zero or more (possibly disconnected) pools. A pool consists of one or multiple connected hole patches, which will later be filled with water. In the beginning, you start with a piece of land where each patch is either a hole in the ground (’.’) or flat grass (’#’). In order to transform this land into a pool area, you must adhere to the following:
    • You can leave a patch as it is. This costs nothing.
    • If the patch is grass in the beginning, you can dig a hole there. This costs d EUR.
    • If the patch is a hole in the beginning, you can fill the hole and put grass on top. This costs f EUR.
    • You must place special boundary elements along each edge running between a final grass patch and a final hole patch, to ensure that water does not leak from the pool. This costs b EUR per boundary element.
    • The outermost rows and columns of the pool area must always be grass.
    You are given the task of calculating the cost of the cheapest possible pool area given the layout of the existing piece of land.

    Input

    On the first line a positive integer: the number of test cases, at most 100. After that per test case:
    • one line with two integers w and h (2 ≤ w, h ≤ 50): the width and height of the building site.
    • one line with three integers d, f and b (1 ≤ d, f, b ≤ 10000): the costs for digging a new hole, filling an existing hole, and building a boundary element between a pool and grass patch.
    • h lines of w characters each, denoting the layout of the original building site.

    Output

    Per test case:
    • one line with an integer: the cost of building the cheapest possible pool area from the original piece of land.

    Sample Input

    3
    3 3
    5 5 1
    #.#
    #.#
    ###
    5 4
    1 8 1
    #..##
    ##.##
    #.#.#
    #####
    2 2
    27 11 11
    #.
    .#

    Sample Output

    9
    27
    22

    分析

    题目大概说一个n*m的土地,土地上每一个格子要嘛是洞要嘛是草地,可以花费d的价钱把草地挖成洞,或者花费f的价钱把洞填成草地,但是要保证土地的边界是草地。之后会在洞的外围围篱笆,每单位篱笆花费b。问最少的总花费。

    • 这题相当于要把土地划分到两个集合,草地和洞。
    • 原本是草地的划分到草地的代价是0,而原本是洞的划分到草地代价是f;划分到洞同理。不过,由于土地边界必须是草地,所以对于边界划分为洞的代价应该为无穷大。
    • 对于两个相邻的地,如果一个划分到洞另一个划分到草地,那就会产生b的费用。

    于是就是最小割,二者选一,不同产生费用的模型。。

    1. 新建源点和汇点,并把各个地看成点
    2. 源点向所有是草地的点连容量d的边
    3. 所有是洞的点向汇点连容量f的边
    4. 源点向所有土地外围的点连容量INF的边
    5. 对于相邻的两点,之间连容量b的边
    6. 最小割即为答案

    代码

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    using namespace std;
    #define INF (1<<30)
    #define MAXN 2555
    #define MAXM 2555*2555
    
    struct Edge{
        int v,cap,flow,next;
    }edge[MAXM];
    int vs,vt,NE,NV;
    int head[MAXN];
    
    void addEdge(int u,int v,int cap){
        edge[NE].v=v; edge[NE].cap=cap; edge[NE].flow=0;
        edge[NE].next=head[u]; head[u]=NE++;
        edge[NE].v=u; edge[NE].cap=0; edge[NE].flow=0;
        edge[NE].next=head[v]; head[v]=NE++;
    }
    
    int level[MAXN];
    int gap[MAXN];
    void bfs(){
        memset(level,-1,sizeof(level));
        memset(gap,0,sizeof(gap));
        level[vt]=0;
        gap[level[vt]]++;
        queue<int> que;
        que.push(vt);
        while(!que.empty()){
            int u=que.front(); que.pop();
            for(int i=head[u]; i!=-1; i=edge[i].next){
                int v=edge[i].v;
                if(level[v]!=-1) continue;
                level[v]=level[u]+1;
                gap[level[v]]++;
                que.push(v);
            }
        }
    }
    
    int pre[MAXN];
    int cur[MAXN];
    int ISAP(){
        bfs();
        memset(pre,-1,sizeof(pre));
        memcpy(cur,head,sizeof(head));
        int u=pre[vs]=vs,flow=0,aug=INF;
        gap[0]=NV;
        while(level[vs]<NV){
            bool flag=false;
            for(int &i=cur[u]; i!=-1; i=edge[i].next){
                int v=edge[i].v;
                if(edge[i].cap!=edge[i].flow && level[u]==level[v]+1){
                    flag=true;
                    pre[v]=u;
                    u=v;
                    //aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap));
                    aug=min(aug,edge[i].cap-edge[i].flow);
                    if(v==vt){
                        flow+=aug;
                        for(u=pre[v]; v!=vs; v=u,u=pre[u]){
                            edge[cur[u]].flow+=aug;
                            edge[cur[u]^1].flow-=aug;
                        }
                        //aug=-1;
                        aug=INF;
                    }
                    break;
                }
            }
            if(flag) continue;
            int minlevel=NV;
            for(int i=head[u]; i!=-1; i=edge[i].next){
                int v=edge[i].v;
                if(edge[i].cap!=edge[i].flow && level[v]<minlevel){
                    minlevel=level[v];
                    cur[u]=i;
                }
            }
            if(--gap[level[u]]==0) break;
            level[u]=minlevel+1;
            gap[level[u]]++;
            u=pre[u];
        }
        return flow;
    }
    
    char map[55][55];
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            int n,m;
            scanf("%d%d",&m,&n);
            int d,f,b;
            scanf("%d%d%d",&d,&f,&b);
            for(int i=0; i<n; ++i){
                for(int j=0; j<m; ++j){
                    scanf(" %c",&map[i][j]);
                }
            }
    
            vs=n*m; vt=vs+1; NV=vt+1; NE=0;
            memset(head,-1,sizeof(head));
    
            for(int i=0; i<n; ++i){
                for(int j=0; j<m; ++j){
                    if(i==0 || i==n-1 || j==0 || j==m-1) addEdge(vs,i*m+j,INF);
                    if(map[i][j]=='#') addEdge(vs,i*m+j,d);
                    else addEdge(i*m+j,vt,f);
                    if(i+1<n){
                        addEdge(i*m+j,(i+1)*m+j,b);
                        addEdge((i+1)*m+j,i*m+j,b);
                    }
                    if(j+1<m){
                        addEdge(i*m+j,i*m+j+1,b);
                        addEdge(i*m+j+1,i*m+j,b);
                    }
                }
            }
            printf("%d
    ",ISAP());
        }
        return 0;
    }
    
  • 相关阅读:
    Golang gRPC 入门
    ProtoBuf编解码
    Proto3语法入门
    Golang RPC入门
    Windows用mstsc(远程桌面)远程Ubuntu 12.04时无法显示Ubuntu桌面解决办法
    ABAPSM30配置TCODE
    eclipselog4j.properties配置
    Hadoop—配置3个副本,但是实际只有1个副本。
    Hadoop—org.apache.hadoop.io.nativeio.NativeIO$Windows.access0
    Jmeter BeanShell使用场景
  • 原文地址:https://www.cnblogs.com/WABoss/p/5751922.html
Copyright © 2011-2022 走看看