zoukankan      html  css  js  c++  java
  • 染方块-color

    http://oj.saikr.com/problem/IPC3-J

    染方块这个题还是蛮套路的。

    之前遇到过一个题,题意大概是有云,小岛,水,用二维矩阵来表示。云下面可以是小岛也可以是水,不知道是啥,然后让干啥干啥,也是网络流做。

    关于染方块的比赛历程为:倒着坐,先把绿色周围的空白方块染成红色,最后再check每一个红块,看看删除它对答案造成的影响。它这个影响是很难check的,影响是相互的,结果就是wa,后来想过dp,复杂度无法接受,图论,不会建图。

    正解就是网络流啦。超级源点S,超级汇点T,S向所有绿点连容量为1的边,绿点向它上下左右4个方向的白点连容量为1的边,然后这些白点再向T连容量为1的边。答案为cnt(green)+cnt(绿色周围的白点)-maxflow。

    对于一个绿点而言,如果它变成白点,那么它对答案的贡献为1,如果存在一个S经它到T的流,

    那么它对最大流的贡献为1,随之把自己对答案的贡献消掉了。也就是有maxflow数量的绿点一定是需要把周围一个白点变红的,剩下的绿点都流不出去,也就能对答案产生真正的一个贡献。

    #include <bits/stdc++.h>
    #define inf 233333333
    #define N 500010
    #define p(a) putchar(a)
    #define For(i,a,b) for(int i=a;i<=b;++i)
    //by war
    //2020.11.17
    using namespace std;
    int n,m,x,y,v,maxflow,tot,cnt,ans;
    int head[N],deep[N],cur[N],num[100][100];
    int X[]={-1,1,0,0};
    int Y[]={0,0,1,-1};
    char a[100][100];
    struct node{
        int n;
        int v;
        int next;
    }e[N];
    queue<int>q;
    
    void in(int &x){
        int y=1;char c=getchar();x=0;
        while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
        while(c<='9'&&c>='0'){ x=(x<<1)+(x<<3)+c-'0';c=getchar();}
        x*=y;
    }
    void o(int x){
        if(x<0){p('-');x=-x;}
        if(x>9)o(x/10);
        p(x%10+'0');
    }
    
    void push(int x,int y,int v){
        e[tot].n=y;
        e[tot].v=v;
        e[tot].next=head[x];
        head[x]=tot++;
    }
    
    bool bfs(int s,int t){
        memset(deep,-1,sizeof(deep));
        For(i,0,cnt)
            cur[i]=head[i];
        deep[s]=0;
        q.push(s);
        while(!q.empty()){
            int now=q.front();
            q.pop();
            for(int i=head[now];i!=-1;i=e[i].next)
                if(deep[e[i].n]==-1 && e[i].v>0){
                    deep[e[i].n]=deep[now]+1;
                    q.push(e[i].n);
                }
        }
        return deep[t]!=-1;
    }
    int dfs(int now,int t,int lim){
        if(now==t||lim==0)
            return lim;
        int flow=0,f;
        for(int i=cur[now];i!=-1;i=e[i].next){
            cur[now]=i;
            if(deep[e[i].n]==deep[now]+1 && (f=dfs(e[i].n,t, min(lim,e[i].v) ))){
                flow+=f;
                lim-=f;
                e[i].v-=f;
                e[i^1].v+=f;
                if(!lim) break;
            }
        }
        return flow;
    }
    
    void dinic(int s,int t){
        while(bfs(s,t)){
            maxflow+=dfs(s,t,inf);
        }
    }
    
    int main(){
        scanf("%s",a[1]+1);
        n=strlen(a[1]+1);
        For(i,2,n) scanf("%s",a[i]+1);
        memset(head,-1,sizeof(head));
        For(i,1,n)
            For(j,1,n){
                if(a[i][j]=='O'){
                    ++cnt;
                    num[i][j]=cnt;
                    push(0,cnt,1);
                    push(cnt,0,0);
                }
            }
        For(i,1,n)
            For(j,1,n){
                if(a[i][j]=='.'){
                    For(k,0,3){
                        int tempx=i+X[k],tempy=j+Y[k];
                        if(tempx>=1 && tempx<=n && tempy>=1 && tempy<=n && a[tempx][tempy]=='O'){
                            ++cnt;
                            num[i][j]=-cnt;
                            break;
                        }
                    }
                    For(k,0,3){
                        int tempx=i+X[k],tempy=j+Y[k];
                        if(tempx>=1 && tempx<=n && tempy>=1 && tempy<=n && a[tempx][tempy]=='O'){
                            push(num[tempx][tempy],cnt,1);
                            push(cnt,num[tempx][tempy],0);
                        }
                    }
                }
            }
        ++cnt;
           For(i,1,n)
               For(j,1,n){
                   ans+=(a[i][j]=='O' || a[i][j]=='.');
                   if(num[i][j]<0){
                       push(-num[i][j],cnt,1);
                       push(cnt,-num[i][j],0);
                   }
               }
        dinic(0,cnt);
        o(ans-maxflow);
        return 0;
    }
     
  • 相关阅读:
    Ubuntu18.04安装配置
    Ubuntu Terminal「控制台」
    Ubuntu16.04系统安装
    UEFI Install CentOS 7
    安装Ubuntu16.04后要做的事
    Ubuntu Google Chrome
    Nuke Linux Crack
    Selenium3自动化测试实战 基于Python语言
    函数基础
    Jenkins持续集成
  • 原文地址:https://www.cnblogs.com/war1111/p/13993857.html
Copyright © 2011-2022 走看看