Leetcode 6106、统计无向图中无法互相到达点对数

这篇博客详细解析了LeetCode第6106题,探讨如何统计在一个无向图中无法通过边相互到达的点对数量。文中介绍了三种解决方案,包括使用并查集、深度优先搜索(DFS)和广度优先搜索(BFS)的方法。

Leetcode 6106、统计无向图中无法互相到达点对数

在这里插入图片描述

方法一、并查集

class Solution {
    public long countPairs(int n, int[][] edges) {
        Union union = new Union(n, edges);
        for(int[] edge : edges) {
            union.union(edge[0], edge[1]);
        }
        return union.getCount();
    }

    class Union{
        int[] parent;

        public Union(int n, int[][] edges) {
            parent = new int[n];
            for(int i = 0; i < n; i++) {
                parent[i] = i;
            }
        }

        public int find(int i) {
            if (parent[i] != i) parent[i] = find(parent[i]);
            return parent[i];
        }

        public void union(int x, int y) {
            int rootx = find(x);
            int rooty = find(y);
            if(rooty != rootx) {
                if(rootx >= rooty) {
                    parent[rooty] = rootx;
                }else{
                    parent[rootx] = rooty;
                }
            }
        }

        public long getCount() {
            long res = 0;
            Map<Integer,Integer> cnt = new HashMap<>();
            for(int i = 0; i < parent.length; i++){
                int root = find(i);
                cnt.put(root, cnt.getOrDefault(root,0) + 1);
            }
            for(int c : cnt.values()){
                res += 1L * (parent.length - c) * c;
            }
            return res / 2;
        }
    }
}

方法二、DFS

class Solution {
    List<List<Integer>> lists = new ArrayList<>();
    public long countPairs(int n, int[][] edges) {
        long ans = 0;

        for(int i = 0; i < n; i++) {
            lists.add(new ArrayList<>());
        }
        for(int[] edge : edges) {
            lists.get(edge[0]).add(edge[1]);
            lists.get(edge[1]).add(edge[0]);
        }
        /**
            visited数组每一个位置初始化为Integer.MAX_VALUE,
            如果当前位置的值等于Integer.MAX_VALUE说明
            不属于任何连通分量,使用dfs算法,
            当前下标i作为连通分量的id
        **/

作者:long-xiao-mao
链接:https://leetcode.cn/problems/count-unreachable-pairs-of-nodes-in-an-undirected-graph/solution/by-long-xiao-mao-m0c9/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
        int[] visited = new int[n];
        Arrays.fill(visited, Integer.MAX_VALUE);

        for(int i = 0; i < n; i++) {
            if(visited[i] == Integer.MAX_VALUE) {
                dfs(i, visited, i);
            }
        }

        for(int i = 0; i < n; i++) {
            if(visited[i] == Integer.MAX_VALUE) {
                visited[i] = i;
            }
        }

        Map<Integer, Integer> map = new HashMap<>();
        for(int i = 0; i < n; i++) {
            map.put((int) visited[i], map.getOrDefault(visited[i], 0) + 1);
        }
		
		/**
            当前连通分量和其他形成的点对数,就是c * (n - c),
            最后相加除以2就是结果。
        **/
        for(int c : map.values()){
                ans += 1L * (n - c) * c;
            }
        return ans / 2;
    }

    public void dfs(int index, int[] visited, int groupId) {
        if(index >= lists.size() || lists.get(index).size() == 0 || visited[index] == groupId) return;
        List<Integer> list = lists.get(index);
        visited[index] = groupId;
        for(int i = 0; i < list.size(); i++) {
            if(visited[list.get(i)] == Integer.MAX_VALUE) {
                dfs(list.get(i), visited, groupId);
            }
        }
    }
}

方法三:BFS

class Solution {
    List<List<Integer>> lists = new ArrayList<>();
    public long countPairs(int n, int[][] edges) {
        long ans = 0;
        Queue<Integer> queue = new LinkedList<>();

        for (int i = 0; i < n; i++) {
            lists.add(new ArrayList<>());
        }
        for (int[] edge : edges) {
            lists.get(edge[0]).add(edge[1]);
            lists.get(edge[1]).add(edge[0]);
        }
        /**
            visited数组每一个位置初始化为Integer.MAX_VALUE,
            如果当前位置的值等于Integer.MAX_VALUE说明
            不属于任何连通分量。
        **/
        int[] visited = new int[n];
        Arrays.fill(visited, Integer.MAX_VALUE);

        for(int i = 0; i < n; i++) {
            if(queue.isEmpty()) {
                if(visited[i] == Integer.MAX_VALUE) {
                    queue.offer(i);
                    visited[i] = i;
                }else{
                    continue;
                }
            }

            while (!queue.isEmpty()) {
                int curr = queue.poll();
                List<Integer> list = lists.get(curr);
                for(int j = 0; j < list.size(); j++) {
                    if(visited[list.get(j)] == Integer.MAX_VALUE) {
                        queue.offer(list.get(j));
                        visited[list.get(j)] = i;
                    }else {
                        continue;
                    }
                }
            }
        }

        Map<Integer, Integer> map = new HashMap<>();
        for(int i = 0; i < n; i++) {
            map.put(visited[i], map.getOrDefault(visited[i], 0) + 1);
        }

        for(int c : map.values()){
                ans += 1L * (n - c) * c;
            }
        return ans / 2;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值