• 【并查集】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);
        }
    }
    作者:老干妈就泡面
    本文版权归作者和博客园共有,欢迎转载,但请给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
  • 相关阅读:
    linux下文件夹的创建、复制、剪切、重命名、清空和删除命令
    Linux 删除文件夹和创建文件的命令
    linux下拷贝整个目录
    星云大师:这十句话 我受用一生
    dex
    瘋耔java语言笔记
    VCC_VID_VTT等的含义
    一位数码管引脚
    android从应用到驱动之—camera(2)---cameraHAL的实现
    android从应用到驱动之—camera(1)---程序调用流程[转]
  • 原文地址:https://www.cnblogs.com/bjxqmy/p/14483982.html
Copyright © 2020-2023  润新知