【连通图】322无向图中连通分量的数目

参考:https://blog.csdn.net/hebtu666/article/details/104424877/?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_title~default-0.control&spm=1001.2101.3001.4242
323. 无向图中连通分量的数目
在这里插入图片描述
注意:
你可以假设在 edges 中不会出现重复的边。而且由于所以的边都是无向边,[0, 1] 与 [1, 0] 相同,所以它们不会同时在 edges 中出现。

答案:
在这里插入图片描述

class Solution {
    public int countComponents(int n, int[][] edges) {
        Union u = new Union(n);
        for(int[] nums : edges){
            int a = nums[0] , b = nums[1];
            u.marge(a,b);
        }
        return u.getNum(n);
    }
}
class Union{
    //并查集本体
    int[] nums;
    //记录根节点层数
    int[] sign;

    //初始化每个节点的祖先为自身并把每棵树层数置为1
    public Union(int n){
        nums = new int[n];
        for(int i = 0 ; i < n ; i++){
            nums[i] = i;
        }
        sign = new int[n];
        Arrays.fill(sign , 1);
    }


    public int find(int x){
        //未优化版本 return x == nums[x] ? nums[x] : find(x);
        if(x != nums[x]){
            //把每个遍历过的节点的父亲节点都置为根节点,相当于缩减了树的层数,增加了宽度
            nums[x] = find(nums[x]);
        }
        return nums[x];
    }

    public void marge(int x , int y){
        //查出两个节点的根节点
        int fx = find(x) , fy = find(y);
        if(fx == fy) return;

        //比较深度,把深度小的连接到深度大的上
        if(sign[fx] >= sign[fy]){
            nums[fy] = fx;
        }else{
            nums[fx] = fy;
        }
        //若深度相同,则fx的深度需要+1
        if(sign[fx] == sign[fy]){
            sign[fx]++;
        }
        //提问:为什么深度不同时,作为祖先的节点深度无变化?
        //答:因为优化后的并查集可以想象为一棵多叉树,深度不同进行合并时,作为被合并的树,合并后最大深度也就跟祖先树相同,所以无需变化。
    }
    
    //判断是否在一棵树中
    public boolean isUnion(int x , int y){
        return find(x) == find(y);
    }

    //对本题的具体操作函数,查询连通分量个数
    public int getNum(int n){
        int ans = 0;
        boolean[] bl = new boolean[n];
        for(int i = 0 ; i < n ; i++){
            int fi = find(i);
            //该树已经计算过,跳过
            if(bl[fi]) continue;
            ans++;
            //记录根
            bl[fi] = true;
        }
        return ans;
    }

}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值