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.


根据题意,所给出的输入为一棵树和一条多余的边,并在输入中找到这条多余的边。这棵树除根节点外,都有一个确定的根节点。
那么就会存在一下三种情况

  • 只有环

    环

这种情况下,选择最后一条组成环的边 remove

  • degree > 1
    入度大于2
    这种情况下,首先记录产生入度为2的边,并且记首先出现的边为 first ,后出现的边为 second 。此时,remove second

  • 有环 且 degree > 1
    both of all
    remove 组成环 且 造成deg > 1的边


class Solution {
private:
    int root[1024];
public:
    vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) {
        for(register int i=0;i<=1000;i++)
            root[i]=0;
        vector<int> first,second;
        int peak=0;
        for(auto& ele: edges){
            peak=max(peak,ele[0]);
            peak=max(peak,ele[1]);
            if(root[ele[1]]==0){
                root[ele[1]]=ele[0];
            }else{
                second=ele;
                first.push_back(root[ele[1]]);
                first.push_back(ele[1]);
                ele[0]=0;
            }
        }
        for(register int i=1;i<=peak;i++)
            root[i]=i;
        for(auto ele : edges){
            if(ele[0]==0)
                continue;
            int rootA=seekRoot(ele[0]);
            int rootB=seekRoot(ele[1]);
            if(rootA==rootB){
                return first.empty()? ele:first;
            }
            root[rootA]=rootB;
        }
        return second;
    }
    int seekRoot(int x){
        if(x==root[x])
            return x;
        else{
            int r=seekRoot(root[x]);
            return root[x]=r;
        }
    }
};

说明:
首先遍历给出的边,寻找是否有 deg > 1 的情况。辅助数组 root ,其中 root[i] 表示节点 i 的父节点,初始值为 0 。如果有 deg > 1 的情况,记录造成这种情况的边。
第二次遍历使用并查集查询是否有环。但遍历的过程不包括 second 。

  • case 1

对应于第一种情况,将会在第一次遍历中记录 且 第二次遍历不返回值。直到函数末尾返回 second 。

  • case 2
    对应于第二种情况,第一次遍历中无记录 且 第二次遍历发现环并返回构成环的边。

  • case 3

对应于第三种情况,采用枚举可能两条边的方法。在第一次遍历中记录 first 和 second 。并且规避了 second 在第二次遍历中被访问。其后进入第二次遍历,如果 first 为组成环 且 造成 deg > 1 的边,则在第二次遍历中将会返回 first ;如果没有在第二次遍历中找到环,则说明产生环 且 deg > 1 的边,是为访问到的 second 。故在遍历结束后返回 second 。

猜你喜欢

转载自blog.csdn.net/white_156/article/details/82729636