• Number of Operations to Make Network Connected 之 并查集


    本题的关键是要知道图论中的一个原理:无向图中, n个结点 至少需要 n-1条边,才能使各个结点相连。

    有两种解法:

    1.用递归遍历的方式,计算有多少个独立的连通的部分,我称为“簇”。需要移动的边就是 簇的个数减1。

    2.使用并查集,计算有几个联通部分,有几条多余的边。如果多余的边小于联通部分,返回-1。否则返回簇的个数减1。

    class Solution {
        Map<Integer, List<Integer>> graph = new HashMap<>();
        boolean[] visited;
        public int makeConnected(int n, int[][] connections) {
            if(connections.length < n-1) return -1;
            for(int[] edge: connections){
                graph.putIfAbsent(edge[0], new ArrayList<>());
                graph.putIfAbsent(edge[1], new ArrayList<>());
                graph.get(edge[0]).add(edge[1]);
                graph.get(edge[1]).add(edge[0]);
            }
            // true代表已经访问过,false代表未访问
            visited = new boolean[n];
            int count = 0;
            for(int i = 0; i < n; i++){
                if(!visited[i]&& dfs(i))
                    count++;
            }
            return count-1;
        }
        public boolean dfs(int cur){
            if(visited[cur]) return true;
            if(!graph.containsKey(cur)) return true;
            visited[cur] = true;
            for(int next: graph.get(cur)){
                if(!visited[next])
                    dfs(next);
            }
            return true;
        }
    }
    class Solution {
        public int makeConnected(int n, int[][] connections) {
            int[] parent = new int[n];
            for(int i = 0; i < n; i++){
                parent[i] = i;
            }
            int extraEdge = 0;
            int count = 0;
            for(int[] edge:connections){
                int p = findParent(parent, edge[0]);
                int q = findParent(parent, edge[1]);
                if(p == q) extraEdge++; //有公共祖先,说明此条边多余,可以去掉
                else parent[q] = p; //如果没有,根据connections矩阵,将两个点连接起来
            }
            for(int i = 0; i < n; i++){
                if(parent[i] == i) count++; //计算有多少个祖先,即多少个 单独的联通量
            }
            return (extraEdge >= count-1) ? count-1 : -1;
        }
        public int findParent(int[] parent, int x){
            while(parent[x] != x){
                x = parent[x];
            }
            return x;
        }
    }
  • 相关阅读:
    C#中的Dictionary字典类介绍
    SQL server 2008r2 file is corrupt
    web service接口 wsdl和asmx有什么区别
    ascx
    C++: C++函数声明的时候后面加const
    C++三种野指针及应对/内存泄露
    C++构造和析构的顺序
    atan2()如何转换为角度
    C++11左值引用和右值引用
    C++ STL详解
  • 原文地址:https://www.cnblogs.com/yawenw/p/13038574.html
Copyright © 2020-2023  润新知