zoukankan      html  css  js  c++  java
  • 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
    ",ans);
            }
            return 0;
    }
    

      

  • 相关阅读:
    Fedora/CentOS使用技巧
    Haproxy配置
    iscsi使用教程
    Linux网络配置
    Linux命令使用
    luogu-1908 逆序对 离散化+树状数组
    算法题目签到表
    [笔记-机器学习]贝叶斯分类器的原理及实现
    [笔记-数据结构]树状数组
    [笔记-数据结构]哈希表
  • 原文地址:https://www.cnblogs.com/xuesu/p/4348839.html
Copyright © 2011-2022 走看看