HDU1198-----并查集

题目链接

用的并查集,据说这题还可以用dfs,没去写。

解法:

11个方块,每个方块有四个方向,上下左右,每个方向两个状态,通或者不通。所以很自然想到用二维数组表示。

上 1  下2  左 3 右 4    通1  不通 0

int data[12][5]={{0,0,0,0,0},{0,1,0,1,0},{0,1,0,0,1},{0,0,1,1,0},{0,0,1,0,1},
                        {0,1,1,0,0},{0,0,0,1,1},{0,1,0,1,1},{0,1,1,1,0},
                            {0,0,1,1,1},{0,1,1,0,1},{0,1,1,1,1}};

然后并查集呢,题目给你的是个网格,有n*m块,所以就有n*m个节点。我把这n*m个点用1~n*m表示

网格中位置   G[i][j]的地方  表示为 i*m+j+1   就把二维数组中的每一个节点转化为 1~n*m的数字了

然后对于每个点  判断他四周的点的连通性是否匹配   若匹配 就合并 

最后遍历找下有几个集合  就是答案

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 5000
int fa[maxn],n,m;
char ch;
int G[55][55];
int data[12][5]={{0,0,0,0,0},{0,1,0,1,0},{0,1,0,0,1},{0,0,1,1,0},{0,0,1,0,1},
                        {0,1,1,0,0},{0,0,0,1,1},{0,1,0,1,1},{0,1,1,1,0},
                            {0,0,1,1,1},{0,1,1,0,1},{0,1,1,1,1}};
int init(){
    memset(fa,0,sizeof(fa));
    for(int i=1;i<=n*m;i++)fa[i]=i;
}
int Find(int x){
    return fa[x]==x?x:fa[x]=Find(fa[x]);
}
int Merge(int x,int y){
    int p1=Find(x),p2=Find(y);
    if(p1!=p2)fa[p2]=p1;
}
int main(){
    while(scanf("%d%d",&n,&m)==2){
        //i*m+j+1  二维转化一维
        getchar();
        if(n<=0&&m<=0)break;
        init();
        memset(G,0,sizeof(G));
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                scanf("%c",&ch);G[i][j]=ch-'A'+1;
            }
            getchar();
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(i>0){//Up
                    if(data[G[i][j]][1]&&data[G[i-1][j]][2])Merge(i*m+j+1,(i-1)*m+j+1);
                }
                if(j>0){//Left
                    if(data[G[i][j]][3]&&data[G[i][j-1]][4])Merge(i*m+j+1,i*m+j-1+1);
                }
                if(i<n-1){//Down
                    if(data[G[i][j]][2]&&data[G[i+1][j]][1])Merge(i*m+j+1,(i+1)*m+j+1);
                }
                if(j<m-1){//Right
                    if(data[G[i][j]][4]&&data[G[i][j+1]][3])Merge(i*m+j+1,i*m+j+1+1);
                }
            }
        }
        int ans=0;
        for(int i=1;i<=n*m;i++){
            if(Find(i)==i)ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/holly_Z_P_F/article/details/81319382