zoj3781

zoj3781
赛场上堵在了缩点上emmmmm
把原始图相同颜色的方块缩成一个点,然后与它周围不同颜色的联通块连双向边,然后枚举每个点然后求最大深度的最小值
因为每次翻转都相当于深度+1(可以手动模拟一下

#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<set>
#include<map>
#include<stack>
#include<cstring>
#define inf 2147483647
#define ls rt<<1
#define rs rt<<1|1
#define lson ls,nl,mid,l,r
#define rson rs,mid+1,nr,l,r
#define N 100010
#define For(i,a,b) for(register int i=a;i<=b;i++)
#define p(a) putchar(a)
#define g() getchar()

using namespace std;
int T;
int n,m;
int deep[1700];
char a[1700][1700];
bool b[1700][1700];
int col[1700][1700];
bool vis[1700][1700],v[1700];
int cnt;
int ans;
queue<int>q;

struct node{
    int n;
    node *next;
}*e[1000000];

void in(int &x){
    int y=1;
    char c=g();x=0;
    while(c<'0'||c>'9'){
        if(c=='-')y=-1;
        c=g();
    }
    while(c<='9'&&c>='0'){
        x=(x<<1)+(x<<3)+c-'0';c=g();
    }
    x*=y;
}
void o(int x){
    if(x<0){
        p('-');
        x=-x;
    }
    if(x>9)o(x/10);
    p(x%10+'0');
}

void clean(){
    For(i,1,n)
        For(j,1,m){
            
            vis[i][j]=0;
            col[i][j]=0;
        }
    For(i,1,n*m)
        For(j,1,n*m){
            b[j][i]=0;
            b[i][j]=0;
        }

    For(i,1,1600)
        e[i]=0;
    cnt=0;
    ans=inf;
        
}

void push(int x,int y){
    node *p;
    p=new node();
    p->n=y;
    if(e[x]==0)
        e[x]=p;
    else{
        p->next=e[x]->next;
        e[x]->next=p;
    }
}

void dfs(int x,int y,char f,int color){
    if(x<1||y<1||x>n||y>m)
        return;
    if(vis[x][y])
        return;
    if(a[x][y]==f){
        vis[x][y]=1;
        col[x][y]=color;
        dfs(x-1,y,f,color);
        dfs(x,y-1,f,color);
        dfs(x,y+1,f,color);
        dfs(x+1,y,f,color);
    }
}

void ccc(int x,int y){
    if(x<1||y<1||x>n||y>m)
        return;
    vis[x][y]=0;
    if(x-1>0&&!b[col[x][y]][col[x-1][y]]){
        if(col[x][y]!=col[x-1][y]){
            push(col[x][y],col[x-1][y]);
            push(col[x-1][y],col[x][y]);
            b[col[x][y]][col[x-1][y]]=1;
            b[col[x-1][y]][col[x][y]]=1;
        }
        if(vis[x-1][y])
            ccc(x-1,y);
    }
    if(y-1>0&&!b[col[x][y]][col[x][y-1]]){
        if(col[x][y]!=col[x][y-1]){
            push(col[x][y],col[x][y-1]);
            push(col[x][y-1],col[x][y]);
            b[col[x][y]][col[x][y-1]]=1;
            b[col[x][y-1]][col[x][y]]=1;
        }
        if(vis[x][y-1])
            ccc(x,y-1);
    }
    if(x+1<=n&&!b[col[x][y]][col[x+1][y]]){
        if(col[x][y]!=col[x+1][y]){
            push(col[x][y],col[x+1][y]);
            push(col[x+1][y],col[x][y]);
            b[col[x][y]][col[x+1][y]]=1;
            b[col[x+1][y]][col[x][y]]=1;
        }
        if(vis[x+1][y])
            ccc(x+1,y);
    }
    if(y+1<=m&&!b[col[x][y]][col[x][y+1]]){
        if(col[x][y]!=col[x][y+1]){
            push(col[x][y],col[x][y+1]);
            push(col[x][y+1],col[x][y]);
            b[col[x][y]][col[x][y+1]]=1;
            b[col[x][y+1]][col[x][y]]=1;
        }
        if(vis[x][y+1])
            ccc(x,y+1);
    }
}

void bfs(int x){
    deep[x]=0;
    q.push(x);
    For(i,1,cnt)
        v[i]=0;
    v[x]=1;
    int ss=0;
    while(!q.empty()){
        int t=q.front();q.pop();
        for(node *i=e[t];i;i=i->next)
            if(!v[i->n]){
                v[i->n]=1;
                q.push(i->n);
                deep[i->n]=deep[t]+1;
                ss=max(ss,deep[i->n]);
            }
    }
    ans=min(ss,ans);
}

int main(){
    in(T);
    while(T--){
        in(n);in(m);
        clean();
        For(i,1,n)
            For(j,1,m)
                cin>>a[i][j];
        For(i,1,n)
            For(j,1,m)
                if(!vis[i][j])
                    dfs(i,j,a[i][j],++cnt);        
        ccc(1,1);
        For(i,1,cnt)
            bfs(i);
        o(ans);p('\n');
    }
    return 0;
}
View Code

 

posted @ 2019-03-18 17:05  WeiAR  阅读(286)  评论(0编辑  收藏  举报