Redundant_Connection_II

本文介绍了一种解决有根树中冗余连接问题的算法。该算法通过检测节点是否有多余的父节点或形成环路来确定哪条边是多余的,并提供了具体的实现代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:

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.

思路:在有根树只有一条边多余的情况下,有两种情况下无法构成树,一种是一个节点有两个父节点,另一种是构成环。如果没有找到有两个父节点的节点,就返回找到的构成环的一边,如果找到有两个父节点的节点就检查去掉其中一条剩余边能不能构成一棵树(若图中无环,删去一边便是一棵树,若有环,且有一条边指向一点,使该节点有两个父节点,那么要在指向拥有两个父节点的节点的两条边中找到同时符合这两个条件的边,因为题中说只有一条多余边)

public class Redundant_Connection_II {	
	public static int[] findRedundantDirectedConnection(int[][] edges) 
	{
		if(edges==null||edges.length==0)
			return null;
		int twoParent[] = findTwoParents(edges);
		if(twoParent!=null)
		{
			//这里检查顺序一定要先检查最新监测出的指向拥有两个父节点的节点的边
			//就像example1,若两条边均符合条件,那么要返回最新出现的答案
			if(findHoop(edges,twoParent[1])==null)
				return edges[twoParent[1]];
			else
				return edges[twoParent[0]];
		}        
		return findHoop(edges,Integer.MIN_VALUE);
    }
	//寻找指向拥有两个父节点的节点的两条边
	public static int[] findTwoParents(int[][] edges)
	{
		boolean flag = true;
		//这里存放的是指向拥有两个父节点的节点的两条边的下标
		int result[] = new int[2];
		//每个节点父节点个数
		int count[] = new int[edges.length+1];
		//指向该节点的边下标
		int toward[] = new int[edges.length+1];
		for(int i=0;i<edges.length;i++)
		{
			int edge[] = edges[i];
			count[edge[1]-1] += 1;
			if(count[edge[1]-1]==2)
			{
				flag = false;
				result[0] = toward[edge[1]-1];
				result[1] = i;
				break;
			}
			toward[edge[1]-1] = i;
		}		
		if(flag)
			return null;
		return result;
	}
	//寻找回环,并且检查去掉index边有无回环
	public static int[] findHoop(int[][] edges,int index)
	{
		boolean flag = true;
		int result[] = new int[2];
		int root[] = new int[edges.length+1];
		for(int i=0;i<edges.length+1;i++)
			root[i] = i+1;
		for(int i=0;i<edges.length;i++)
		{
			if(i==index)
				continue;
			int edge[] = edges[i];
			if(root[edge[0]-1]==root[edge[1]-1])
			{
				flag = false;
				result[0] = edge[0];
				result[1] = edge[1];
				continue;
			}
			int original = root[edge[1]-1];
			for(int j=0;j<edges.length+1;j++)
			{
				if(root[j]==original)
					root[j] = root[edge[0]-1];
			}
		}
		if(flag)
			return null;
		return result;
	}
	public static void main(String[] args) {
//		int[][] edges = {{1,2}, {2,3}, {3,4}, {4,1}, {1,5}};
//		int[][] edges = {{2,1},{3,1},{4,2},{1,4}};
		int[][] edges = {{1,2}, {1,3}, {2,3}};
		int result[] = findRedundantDirectedConnection(edges);

//		int result[] = findHoop(edges,-1);
//		int result[] = findTwoParents(edges);
		
		for(int i=0;i<result.length;i++)
			System.out.println(result[i]);
	}
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值