UVA572 (并查集解法)

紫书第六章的题,用并查集重写一遍,果然还是书上给的dfs方法更简单......

一开始用fa[i*m+j] != i*m+j 来判断是否访问过,虽然没想出来为什么WA,但是确实不如用vis稳

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int fa[10500],m,n,cnt,vis[105][105];
char mp[105][105];
int find(int x){return fa[x] == x?x:fa[x] = find(fa[x]);}
void merge(int x,int y){
    int fx = find(x);
    int fy = find(y);
    if(fx == fy) return ;
    fa[fx] = fy;
}
void dfs(int x,int y,int fx,int fy){
    if(x<0 || x>=m || y<0 || y>=n) return;
    if(vis[x][y] || mp[x][y] == '*') return;
    vis[x][y] = 1;
    //cout<<"x || y || fx || fy : "<<x<<" || "<<y<<" || "<<fx<<" || "<<fy<<endl;
    if(fx != -1) merge(x*m+y,fx*m+fy);
    for(int i = -1;i<2;i++){
        for(int j = -1;j<2;j++){
            if(!i && !j) continue;
            dfs(x+i,y+j,x,y);
        }
    }
}
int main(){
    while(scanf("%d%d",&m,&n) == 2 && m && n){
        cnt = 0;
        memset(vis,0,sizeof(vis));
        for(int i = 0;i<m;i++) scanf("%s",mp[i]);
        for(int i = 0;i<10500;i++) fa[i] = i;
        for(int i = 0;i<m;i++)
            for(int j = 0;j<n;j++)
                if(!vis[i][j] && mp[i][j] == '@') dfs(i,j,-1,-1),cnt++;
        printf("%d\n",cnt);
    }
    return 0;
}

 

posted @ 2017-08-24 08:09  Invisible_full_moon  阅读(294)  评论(0编辑  收藏  举报