LeetCode-684. Redundant Connection

description

In this problem, the tree refers to a connected and acyclic undirected graph.

Enter a graph consisting of a tree with N nodes (the node values ​​do not repeat 1, 2, ..., N) and an additional edge. The two vertices of the additional edge are contained between 1 and N. This additional edge does not belong to an existing edge in the tree.

The resulting graph is a two-dimensional array of edges. The elements of each edge are a pair of [u, v], satisfying u <v, representing the edges of the undirected graph connecting vertices u and v.

Return an edge that can be deleted so that the resulting graph is a tree with N nodes. If there are multiple answers, the last edge in the two-dimensional array is returned. The answer side [u, v] should satisfy the same format u <v.

Example 1:

Input: [[1,2], [1,3], [2,3]]
Output: [2,3]
Explanation: The given undirected graph is:
  1
 / \
2-3
Example 2:

Input: [[1,2], [2,3], [3,4], [1,4], [1,5]]
Output: [1,4]
Explanation: The given undirected graph is:
5-1-2
    | |
    4-3
Note:

The size of the input two-dimensional array is 3 to 1000.
The integers in the two-dimensional array are between 1 and N, where N is the size of the input array.
Update (2017-09-26):
We have re-examined the problem description and test cases, and it is clear that the graph is undirected. For directed graphs, see Redundant Connection II for details. We apologize for any inconvenience caused.

Source: LeetCode
Link: https://leetcode-cn.com/problems/redundant-connection/
 

Solve

   class UnionFind {
    public:
        UnionFind(int n) : count(n) {
            parent.reserve(count + 1);
            for (int i = 0; i <= count; ++i) {
                parent[i] = i;
            }
            rank.resize(count + 1, 1);  // 初始每个的层级均为1
        }

        bool isConnected(int p, int q) {
            return find(p) == find(q);
        }

        void unionElements(int p, int q) {
            int proot = find(p);
            int qroot = find(q);
            if (proot == qroot) {
                return;
            }

            if (rank[proot] < rank[qroot]) {
                parent[proot] = qroot;
            } else if (rank[proot] > rank[qroot]) {
                parent[qroot] = proot;
            } else {
                // rank[proot] == rank[qroot]
                parent[proot] = qroot;
                ++rank[qroot];  // proot ”挂载“到qroot下面,本来两个层级一致,现在需要增加1
            }
        }

    private:
        int find(int p) {
            // 效率低,但是相对1e在unionElements中的逐个赋值效率要高
            // 路径压缩优化实例
            // 假设有 4 -> 3 -> 2 -> 1 -> 0的指向,则通过路径压缩优化后变为
            // 1 -> 0
            // 3 -> 2 -> 0
            // 4 -> 2 -> 0
            while (p != parent[p]) {
                parent[p] = parent[parent[p]]; // 路径压缩优化,请细品
                p = parent[p];
            }
            return p;
        }

    private:
        std::vector<int> parent;
        int count;
        std::vector<int> rank;
    };

    class Solution {
    public:
        // 方法一,单独定义一个并查集类辅助实现
        vector<int> findRedundantConnection_1e(vector<vector<int>> &edges) {
            UnionFind uf(edges.size());
            for (auto p  :  edges) {
                if (!uf.isConnected(p[0], p[1])) {
                    uf.unionElements(p[0], p[1]);
                    continue;
                }
                return p;
            }
            return vector<int>(); // 不存在这样的边,返回空
        }

        // 方法二,不定义并查集类,仅实现两个辅助函数
        vector<int> findRedundantConnection(vector<vector<int>> &edges) {
            const int n = edges.size();
            vector<int> parent(n + 1, 0);
            for (int i = 0; i <= n; ++i) {
                parent[i] = i;
            }
            for (auto p : edges) {
                if (!isConnected(parent, p[0], p[1])) {
                    unionElements(parent, p[0], p[1]);
                    continue;
                }
                return p;
            }
            return vector<int>();
        }

    private:
        int find(vector<int> &parent, int p) {
            while (p != parent[p]) {
                parent[p] = parent[parent[p]];
                p = parent[p];
            }
            return p;
        }

        bool isConnected(vector<int> &parent, int p, int q) {
            int pParent = find(parent, p);
            int qParent = find(parent, q);
            return pParent == qParent;
        }

        void unionElements(vector<int> &parent, int p, int q) {
            int pParent = find(parent, p);
            int qParent = find(parent, q);
            if (pParent != qParent) {
                parent[pParent] = qParent;
            }
        }
    };

 

Guess you like

Origin blog.csdn.net/u010323563/article/details/112568757