[LeetCode] 685. Redundant Connection II 冗余的連接之二


 

In this problem, a rooted tree is a directed graph such that, there is exactly one node (the root) for which all other nodes are descendants of this node, plus every node has exactly one parent, except for the root node which has no parents.

The given input is a directed graph that started as a rooted tree with N nodes (with distinct values 1, 2, ..., N), with one additional directed edge added. The added edge has two different vertices chosen from 1 to N, and was not an edge that already existed.

The resulting graph is given as a 2D-array of edges. Each element of edges is a pair [u, v] that represents a directed edge connecting nodes u and v, where u is a parent of child v.

Return an edge that can be removed so that the resulting graph is a rooted tree of N nodes. If there are multiple answers, return the answer that occurs last in the given 2D-array.

Example 1:

Input: [[1,2], [1,3], [2,3]]
Output: [2,3]
Explanation: The given directed graph will be like this:
  1
 / \
v   v
2-->3

 

Example 2:

Input: [[1,2], [2,3], [3,4], [4,1], [1,5]]
Output: [4,1]
Explanation: The given directed graph will be like this:
5 <- 1 -> 2
     ^    |
     |    v
     4 <- 3

 

Note:

  • The size of the input 2D-array will be between 3 and 1000.
  • Every integer represented in the 2D-array will be between 1 and N, where N is the size of the input array.

 

這道題是之前那道 Redundant Connection 的拓展,那道題給的是無向圖,只需要刪掉組成環的最后一條邊即可,歸根到底就是檢測環就行了。而這道題給的是有向圖,整個就復雜多了,因為有多種情況存在,比如給的例子1就是無環,但是有入度為2的結點3。再比如例子2就是有環,但是沒有入度為2的結點。其實還有一種情況例子沒有給出,就是既有環,又有入度為2的結點。好,現在就來總結一下這三種情況:

第一種:無環,但是有結點入度為2的結點(結點3)

[[1,2], [1,3], [2,3]]

 

  1
 / \
v   v
2-->3

 

第二種:有環,沒有入度為2的結點

[[1,2], [2,3], [3,4], [4,1], [1,5]]

 

5 <- 1 -> 2
     ^    |
     |    v
     4 <- 3

 

第三種:有環,且有入度為2的結點(結點1)

[[1,2],[2,3],[3,1],[1,4]]

 

     4
    /
   v
   1
 /  ^
v    \
2 -->3

 

對於這三種情況的處理方法各不相同,首先對於第一種情況,返回的產生入度為2的后加入的那條邊 [2, 3],而對於第二種情況,返回的是剛好組成環的最后加入的那條邊 [4, 1],最后對於第三種情況返回的是組成環,且組成入度為2的那條邊 [3, 1]。

明白了這些,先來找入度為2的點,如果有的話,那么將當前產生入度為2的后加入的那條邊標記為 second,前一條邊標記為 first。然后來找環,為了方便起見,找環使用聯合查找 Union Find 的方法,可參見 Redundant Connection 中的解法三。當找到了環之后,如果 first 不存在,說明是第二種情況,返回剛好組成環的最后加入的那條邊。如果 first 存在,說明是第三種情況,返回 first。如果沒有環存在,說明是第一種情況,返回 second,參見代碼如下:

 

class Solution {
public:
    vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) {
        int n = edges.size();
        vector<int> root(n + 1, 0), first, second;
        for (auto& edge : edges) {
            if (root[edge[1]] == 0) {
                root[edge[1]] = edge[0];
            } else {
                first = {root[edge[1]], edge[1]};
                second = edge;
                edge[1] = 0;
            }
        }
        for (int i = 0; i <= n; ++i) root[i] = i;
        for (auto& edge : edges) {
            if (edge[1] == 0) continue;
            int x = getRoot(root, edge[0]), y = getRoot(root, edge[1]);
            if (x == y) return first.empty() ? edge : first;
            root[x] = y;
        }
        return second;
    }
    int getRoot(vector<int>& root, int i) {
        return i == root[i] ? i : getRoot(root, root[i]);
    }
};

 

討論:使用聯合查找 Union Find 的方法一般都需要寫個子函數,來查找祖宗結點,上面的解法 getRoot() 函數就是這個子函數,使用遞歸的形式來寫的,其實還可以用迭代的方式來寫,下面這兩種寫法都可以:

 

int getRoot(vector<int>& root, int i) {
    while (i != root[i]) {
        root[i] = root[root[i]];
        i = root[i];
    }
    return i;
}

 

int getRoot(vector<int>& root, int i) {
    while (i != root[i]) i = root[i];
    return i;
}

 

Github 同步地址:

https://github.com/grandyang/leetcode/issues/685

 

類似題目:

Redundant Connection

Friend Circles

Accounts Merge

Number of Islands II

Graph Valid Tree

Number of Connected Components in an Undirected Graph

Similar String Groups

 

參考資料:

https://leetcode.com/problems/redundant-connection-ii/

https://leetcode.com/problems/redundant-connection-ii/discuss/108045/C++Java-Union-Find-with-explanation-O(n)

https://leetcode.com/problems/redundant-connection-ii/discuss/108058/one-pass-disjoint-set-solution-with-explain

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM