【并查集】hdu 1272 小希的迷宫

题目描述:

http://acm.hdu.edu.cn/showproblem.php?pid=3635

 

思路:

这道题等价于,判断所给图是否连通,是否是棵树。

判断是否连通:

已知一棵树的节点个数 = 边的条数 + 1,

若不能满足这个条件,则说明所给数据构成了不止一棵树,即所给图不连通。

判断是否是棵树:

若待合并的两个节点在同一个集合中,则二者相连会构成回路,就不是树了。 

 

代码:

//测试数据:
//1 2 1 2 0 0
//1 2 2 1 0 0
//1 1 0 0
//0 0
//1 2 3 4 0 0
//
//No
//No
//No
//Yes
//No

#include<bits/stdc++.h>
using namespace std;

#define MAX 100001

int room[MAX];
int cnt[MAX];//连通的房间个数 
int points,edges;//节点个数、边条数 
bool fit;//是否符合小希的思路 

//初始化 
void init(){
    points = 1;
    edges = 0;
    fit = true;
    for(int i=1;i<MAX;i++){
        room[i] = i;
        cnt[i] = 1;
    }
}

//寻找节点 x 所在的房间集和 
int find(int x){
    if(x == room[x]){
        return x;
    }
    int root = find(room[x]);
    room[x] = root;
    return root;
}

//合并 
void union_set(int x, int y){
    x = find(x);
    y = find(y);
    
    //若 x 和 y 在同一个集合中,则二者相连会构成回路 
    if(x == y){
        fit = false;
        return;
    }
    
    //优化 
    if(cnt[x] <= cnt[y]){
        room[x] = y;
        cnt[y] += cnt[x];
        points = (points > cnt[y])?points:cnt[y];
    }
    else{
        room[y] = x;
        cnt[x] += cnt[y];
        points = (points > cnt[x])?points:cnt[x];
    }
    //边的条数加一 
    edges++;
}

int main(){
    int x,y;
    init();
    while(scanf("%d %d", &x, &y) && (x != -1 || y != -1)){
        if(x == 0 && y == 0){
            //这道题等价于,判断所给图是否连通,是否是棵树 
            //已知,一棵树的节点个数 = 边的条数 + 1
            //若不满足这个条件,则说明存在着不止一棵树,即所给图不连通 
            if(points != (edges+1)){
                fit = false;
            }
            if(fit){
                printf("Yes
");
            }
            else{
                printf("No
");
            }
            //记得初始化 
            init();
            continue;
        }
        union_set(x, y);
    }
}
作者:老干妈就泡面
本文版权归作者和博客园共有,欢迎转载,但请给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/bjxqmy/p/14483982.html