染方块-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;
}
 

 

posted @ 2020-11-17 14:03  WeiAR  阅读(154)  评论(0编辑  收藏  举报