[LeetCode] (Hard) 685. Redundant Connection II

https://leetcode.com/problems/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 uand 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.

根據題幹描述,一共有兩種違例的可能:1、一個節點被多個節點指向  2、成環 

其中第一個可能是相比於684的無向圖新增的,這就使得這道題不僅僅是消除弱聯通分量這麼簡單。

每一次發現結點違例後刪除邊的優先級也發生了變化:最優先是違反兩個條件的邊,其次是兩個違例中後面那條出現的邊

因爲最優先情況的存在我們需要繼續向後掃描

class Solution {
public:
    vector<int> root;
    vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) {
        root = vector<int>(edges.size()+1);
        for(int i = 0; i < root.size(); ++i){
            root[i] = i;
        }
        
        vector<int> candidate;
        vector<int> res;
        
        for(int i = 0; i < edges.size(); ++i){
            int st = edges[i][0];
            int ed = edges[i][1];
            int stR = getRoot(st);
            int edR = getRoot(ed);
            
            if(edR != ed){
                if(!candidate.empty()){
                    res = {root[ed], ed};
                    break;
                }else{
                    candidate = {root[ed], ed};
                    res = {st, ed};
                }
            }else if(stR == edR){
                if(!candidate.empty()){
                    res = candidate;
                    break;
                }else{
                    candidate = res = {st, ed};
                }
            }else{
                root[ed] = st;
            }
        }
        
        return res;
        
        
    }
    
    int getRoot(int idx){
        while(root[idx] != idx) idx = root[idx];
        return idx;
    }
};

其中candidate用於標記是否已發現至少一種違例,在第一種違例下還用於記錄當前參與討論的邊。

主邏輯如下:

1. 如果發生了第一種違例

1.1. 如果已經發生了第二種違例,則刪除此前的父親邊(這條邊必然參與環的組成)

1.2. 如果沒有發生第二種違例,則記錄當前違例的兩條邊,當前邊優先級更高,當前邊不計入圖中,前邊繼續參與環的檢測

2. 如果發生第二種違例

2.1. 如果已經發生了第一種違例,則刪除第一種爲違例中參與構造環的那條邊

2.2. 如果沒有發生第一種違例,則標記第二種違例的發生,並且按照優先級應當記錄當前邊(比環中其他邊的優先級要高)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章