一【题目类别】
二【题目难度】
三【题目编号】
四【题目描述】
- 在本问题中,有根树指满足以下条件的 有向 图。该树只有一个根节点,所有其他节点都是该根节点的后继。该树除了根节点之外的每一个节点都有且只有一个父节点,而根节点没有父节点。
- 输入一个有向图,该图由一个有着 n 个节点(节点值不重复,从 1 到 n)的树及一条附加的有向边构成。附加的边包含在 1 到 n 中的两个不同顶点间,这条附加的边不属于树中已存在的边。
- 结果图是一个以边组成的二维数组 edges 。 每个元素是一对 [ui, vi],用以表示 有向 图中连接顶点 ui 和顶点 vi 的边,其中 ui 是 vi 的一个父节点。
- 返回一条能删除的边,使得剩下的图是有 n 个节点的有根树。若有多个答案,返回最后出现在给定二维数组的答案。
五【题目示例】
- 示例 1:
输入:edges = [[1,2],[1,3],[2,3]]
输出:[2,3] - 示例 2:
输入:edges = [[1,2],[2,3],[3,4],[4,1],[1,5]]
输出:[4,1]
六【题目注意】
- n == edges.length
- 3 <= n <= 1000
- edges[i].length == 2
- 1 <= ui, vi <= n
七【解题思路】
- 首先计算每个结点的入度,如果入度都为1,就当成无向图来算,那么就和冗余连接I式一样的,加入哪个边形成环了就直接返回即可。如果入度有为2的,就当成有向图来算,则有两个结点指向该结点,这两条边优先删除位于临边数组后边的一条边,若不能连通返回另一条,否则返回该条,具体做法是判断去掉某个边是否还能构成通路,如果可以构成通路,最后都指向根节点,那么返回后一条边,否则不能构成通路,返回前一条边
八【时间频度】
九【代码实现】
- Java语言版
package Graph;
import java.util.Arrays;
public class p685_RedundantConnectionII {
public static void main(String[] args) {
int[][] edges = {
{1, 2},
{1, 3},
{2, 3},
};
int[] res = findRedundantDirectedConnection(edges);
System.out.println("res = " + Arrays.toString(res));
}
public static int[] findRedundantDirectedConnection(int[][] edges) {
int[] degrees = new int[edges.length + 1];
int flag = -1;
for (int[] edge : edges) {
degrees[edge[1]] += 1;
if (degrees[edge[1]] == 2) {
flag = edge[1];
break;
}
}
if (flag == -1) {
int[] nums = new int[edges.length + 1];
for (int k = 0; k < nums.length; k++) {
nums[k] = k;
}
for (int i = 0; i < edges.length; i++) {
int f1 = findRoot(edges[i][0], nums);
int f2 = findRoot(edges[i][1], nums);
if (f1 == f2) {
return edges[i];
}
else {
nums[f1] = f2;
}
}
}
else {
int pre = -1, pre1 = -1;
int[] nums = new int[edges.length + 1];
int i, j, count = 0;
for (i = 0; i < edges.length + 1; i++) {
nums[i] = i;
}
for (i = 0; i < edges.length; i++) {
if (edges[i][1] == flag) {
if (pre == -1) {
pre = i;
} else {
pre1 = i;
break;
}
}
}
int f1 = 0, f2 = 0;
for (i = 0; i < edges.length; i++) {
if (i == pre1) {
continue;
}
f1 = findRoot(edges[i][0], nums);
f2 = findRoot(edges[i][1], nums);
nums[f1] = nums[f2];
}
for (i = 1; i < nums.length; i++) {
if (nums[i] == i) {
count++;
}
}
if (count == 2) {
return edges[pre];
} else {
return edges[pre1];
}
}
return null;
}
public static int findRoot(int n, int[] nums) {
while (nums[n] != n) {
n = nums[n];
}
return n;
}
}
- C语言版
#include<stdlib.h>
#include<stdio.h>
#include<stdbool.h>
#define MAX_GROUPS_COUNT 1001
int g_groups[MAX_GROUPS_COUNT];
void InitGroups()
{
for (size_t i = 0; i < MAX_GROUPS_COUNT; i++)
{
g_groups[i] = i;
}
}
int Find(int id)
{
if (id == g_groups[id])
{
return id;
}
return g_groups[id] = Find(g_groups[id]);
}
int *findRedundantDirectedConnection(int **edges, int edgesSize, int *edgesColSize, int *returnSize)
{
if (edges == NULL || edgesColSize == NULL || returnSize == NULL)
{
return NULL;
}
int *result = (int *)malloc(sizeof(int) * 2);
if (result == NULL)
{
return NULL;
}
InitGroups();
int twoDegreeUv[2][2];
int removeFirst = 0;
int twoDegreeV = MAX_GROUPS_COUNT;
int degrees[MAX_GROUPS_COUNT] = { 0 };
int u, v, uGroupId, vGroupId;
for (int i = 0; i < edgesSize; i++)
{
u = edges[i][0];
v = edges[i][1];
degrees[v] += 1;
if (degrees[v] == 2) {
twoDegreeV = v;
break;
}
}
int saveDegreeCount = 0;
for (int i = 0; i < edgesSize; i++)
{
u = edges[i][0];
v = edges[i][1];
if (v == twoDegreeV)
{
twoDegreeUv[saveDegreeCount][0] = u;
twoDegreeUv[saveDegreeCount][1] = v;
saveDegreeCount += 1;
}
if (v == twoDegreeV && saveDegreeCount == 2)
{
continue;
}
uGroupId = Find(u);
vGroupId = Find(v);
if (uGroupId == vGroupId)
{
removeFirst = 1;
if (twoDegreeV != MAX_GROUPS_COUNT)
{
}
else
{
twoDegreeUv[0][0] = u;
twoDegreeUv[0][1] = v;
break;
}
}
g_groups[vGroupId] = uGroupId;
}
if (removeFirst)
{
result[0] = twoDegreeUv[0][0];
result[1] = twoDegreeUv[0][1];
}
else
{
result[0] = twoDegreeUv[1][0];
result[1] = twoDegreeUv[1][1];
}
*returnSize = 2;
return result;
}
十【提交结果】
- Java语言版
- C语言版