685. Redundant Connection II

56 篇文章 0 订阅
8 篇文章 0 订阅


问题描述

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.

题意理解

N个结点(记作1~N)的一棵树,加上一条边之后变成一个有向图(父亲指向孩子). 求一条边, 删除后可以使图变成一棵树.(如果有多条符合条件的边, 返回在edges数组中的最后一条)

算法分析

(前提: 知道union-find)
由于这个图原来是一棵合法的树, 所以再加一条边会造成

A. 两个点指向同一个孩子 ,
B. 构成一个环.

做union-find, 在union过程中, 找到这样的情况并且分为三种情况:
1. A∩B
2. A
3. B

算法大体流程
1. 在一开始,先查看存不存在两条边指向同一个孩子, 如果有, 记作candidateA, candidateB.
2. 第二步, 在union时检查有没有环.并且分情况找到相应的边.

下面针对以上三种情况进行分析
1. 两个点指向同一个孩子 , 且存在一个环, 如下图
这里写图片描述
如果最后的一条边改成[1, 3]呢? 如下图所示:
这里写图片描述
从直观上可以感受到, 在环中的那条、与其他节点指向同一孩子节点的边(candidate), 即是多余的那一条边
2. 两个点指向同一个孩子 (不存在环)
这种情况比较简单, 直接返回指向同一个孩子的后来的一条边(candidateB)
这里写图片描述
3. 存在环, (但不存在两个节点指向同一个孩子)
这种情况也很简单, 在union时发现会构成环的那条边就是所求边, 如下图
这里写图片描述

具体实现

class Solution {
public:
    vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) {
        vector<int> root(edges.size()+1, 0);
        vector<int> res, candidateA, candidateB;
        if (edges.empty()) return res;

        // step 1, check whether there is a node with 2 parent
        for (auto &edge : edges) {
            if (root[edge[1]]== 0) // edge[1] has no parent
                root[edge[1]] = edge[0];
            else {
                candidateA = {root[edge[1]], edge[1]};
                candidateB = edge;
                edge[1] = 0; // mark the edge with 2 parent
            }
        }

        // step 2, union-find, and check circle
        for (int i = 1; i <= edges.size(); i++) root[i] = i;
        for (auto &edge : edges) {
            if (edge[1] == 0) continue; // the node with 2 parent
            // union. now every node has only 1 parent. find whether exixst a circle
            int u = edge[0], v = edge[1], uroot = find(u, root);
            if (uroot == v) {  // find circle!
                if (candidateA.empty()) // no node with 2 parent 
                    return edge;
                else {  // a node with 2 parent, return the edge inside the circle
                    if (find(candidateA[0]) == v)
                        return candidateA;
                    else
                        return candidateB;
                }  
            }
            root[v] = uroot;
        }
        return candidateB;
    }

    int find(int p, vector<int>& root) {
        while (p != root[p])
            p = find(root[p], root);
        return p;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值