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]]

 / \
v v
-->

第二种:有环,没有入度为2的结点

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

 <-  ->
^ |
| v
<-

第三种:有环,且有入度为2的结点(结点1)

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

    /
v / ^
v \
-->

对于这三种情况的处理方法各不相同,首先对于第一种情况,返回的产生入度为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 + , ), first, second;
for (auto& edge : edges) {
if (root[edge[]] == ) {
root[edge[]] = edge[];
} else {
first = {root[edge[]], edge[]};
second = edge;
edge[] = ;
}
}
for (int i = ; i <= n; ++i) root[i] = i;
for (auto& edge : edges) {
if (edge[] == ) continue;
int x = getRoot(root, edge[]), y = getRoot(root, edge[]);
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 题目讲解汇总(持续更新中...)

[LeetCode] Redundant Connection II 冗余的连接之二的更多相关文章

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

    In this problem, a rooted tree is a directed graph such that, there is exactly one node (the root) f ...

  2. [LeetCode] 685. Redundant Connection II 冗余的连接之 II

    In this problem, a rooted tree is a directed graph such that, there is exactly one node (the root) f ...

  3. [LeetCode] Redundant Connection 冗余的连接

    In this problem, a tree is an undirected graph that is connected and has no cycles. The given input ...

  4. LeetCode 685. Redundant Connection II

    原题链接在这里:https://leetcode.com/problems/redundant-connection-ii/ 题目: In this problem, a rooted tree is ...

  5. [Swift]LeetCode685. 冗余连接 II | Redundant Connection II

    In this problem, a rooted tree is a directed graph such that, there is exactly one node (the root) f ...

  6. [LeetCode] Palindrome Permutation II 回文全排列之二

    Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empt ...

  7. [LeetCode] Arithmetic Slices II - Subsequence 算数切片之二 - 子序列

    A sequence of numbers is called arithmetic if it consists of at least three elements and if the diff ...

  8. [LeetCode] Contains Duplicate II 包含重复值之二

    Given an array of integers and an integer k, return true if and only if there are two distinct indic ...

  9. [LeetCode] Single Number II 单独的数字之二

    Given an array of integers, every element appears three times except for one. Find that single one. ...

随机推荐

  1. mysql新手入门随笔

    1.启动/关闭服务器 第一种方法:通过Notifier 第二种方法: 通过Windows自带的服务管理:计算机右键选择管理弹出框选择"服务和应用程序"里的服务列表,从列表中找到My ...

  2. Java 并发编程实践基础 读书笔记: 第一章 JAVA并发编程实践基础

    1.创建线程的方式: /** * StudySjms * <p> * Created by haozb on 2018/2/28. */ public class ThreadDemo e ...

  3. JavaEE HttpServlet 解析

    上一篇 文章中有提到,GenericServlet 是对 Servlet 的一个通用实现,并提供了一个抽象的 service() 方法.而我们的互联网是使用 Http 协议来通信的,那针对这个&quo ...

  4. 听翁恺老师mooc笔记(2)-第一个程序--&运算符

    使用devC++写hello world 第一步:文件-新建-源代码.然后输入"输出hello world"程序: 注意:写程序时关闭中文输入法,否则语句输入的分号可能会被识别为错 ...

  5. C语言的第一次作业

    一.PTA实验作业 题目1. 温度转换 本题要求编写程序,计算华氏温度150°F对应的摄氏温度.计算公式:C=5×(F−32)/9,式中:C表示摄氏温度,F表示华氏温度,输出数据要求为整型. 1.实验 ...

  6. C语言博客作业—数据类型

    一.PTA实验作业 题目1: 1. 本题PTA提交列表 2. 设计思路 (2)if(输入的n为奇数){ for(行数小于n/2+1时){ for(空格数等于n-2*k+1) printf(" ...

  7. C语言第五次作业--数据类型

    7-2 区位码输入法: 1. 本题PTA提交列表: 2.设计思路: 1.simple定义输入数,character1和character2分别定义低字节和高字节区位码,digit存储取余后的数,sum ...

  8. 团队作业7——第二次项目冲刺(Beta版本12.08)

    项目每个成员的进展.存在问题.接下来两天的安排. 已完成的内容:完成了排行榜的测试.上传头像功能的原型设计.界面优化 计划完成的内容:上传头像功能开发.测试.头像裁剪原型设计 每个人的工作 (有wor ...

  9. C++布隆过滤器

    布隆过滤器 这名词有没有听着好像很 挺高大上的,的确,它也是一种很重要的结构,下面一起看看: 一:说说历史: (Bloom Filter)是由布隆(Burton Howard Bloom)在1970年 ...

  10. python简单路由系统

    # 输入模块名/函数 url = input('请输入网址:') module,func = url.split('/') m = __import__('lib.'+module,fromlist= ...