[PAT]1021. Deepest Root (25)@Java实现

1021. Deepest Root (25)

时间限制
1500 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

A graph which is connected and acyclic can be considered a tree. The height of the tree depends on the selected root. Now you are supposed to find the root that results in a highest tree. Such a root is called the deepest root.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (<=10000) which is the number of nodes, and hence the nodes are numbered from 1 to N. Then N-1 lines follow, each describes an edge by given the two adjacent nodes' numbers.

Output Specification:

For each test case, print each of the deepest roots in a line. If such a root is not unique, print them in increasing order of their numbers. In case that the given graph is not a tree, print "Error: K components" where K is the number of connected components in the graph.

Sample Input 1:
5
1 2
1 3
1 4
2 5
Sample Output 1:
3
4
5
Sample Input 2:
5
1 3
1 4
2 5
3 4
Sample Output 2:
Error: 2 components


从任意一个节点开始进行深度优先遍历,找到离他最远的节点(可能不止一个,记为集合A);第二步:再从A中任意选一个节点出发进行深度优先遍历,找到离他最远的节点(记为集合B),最后最深根就是这两个集合的并集。

证明:第一步找出的节点一定是全局的最深根。

1     根据全局最优解一定是局部最优解的原理:最后全局的最深根一定也是某个局部最优解,比如:因为全局最深的根是固定的,不失一般性,我们就把他们标为1、2、3、4、5,那么从图中中任意一点出发,例如A,从他出发找到的局部最优解一定是在1、2、3、4、5,反之,如不在,也就是说有比1、2、3、4、5更深的节点,我们假设它存在并且成为B,那么可想而知,从1到B肯定要比从1到2要深,这就与1、2、3、4、5是全局最优解矛盾,所以假设不成立。原命题成立。即局部最优解一定在1、2、3、4、5中。

2    由第一步知道局部最优解是固定的,且全局最优解是局部最优解,根据这两条结论,得出:第一次遍历得到的最深的节点就是最深根

由于从最深根出发到最深的叶子节点是相互对称的,所以我们再从当前的最深根出发遍历一次得到其他的最深根,然后做一次去重即可。




package go.jacob.day1017;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

/**
 * 1021. Deepest Root (25)
 * 
 * @author Jacob 一共N个点,有N-1条边。只要components大于1,必定有环。
 *         寻找最远距离的时候,只要使用两次DFS就可以了。原因如下: 树中最远的距离必是距离根节点R最远和次远的两个叶节点的连线。
 *         可以任意选择一个节点,进行深度优先搜索,第一次找到最远的节点。 用刚刚找到的最远节点为根节点做dfs,再次寻找最远节点(可能有多个)
 */
public class Demo1 {
	static int components = 0;
	static int n;
	static ArrayList<Integer>[] matrix;
	static boolean[] visited;
	static int[] deep;

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		matrix = new ArrayList[n + 1];
		for (int i = 1; i < n + 1; i++) {
			matrix[i] = new ArrayList<Integer>();
		}
		visited = new boolean[n + 1];
		deep = new int[n + 1];
		for (int i = 0; i < n - 1; i++) {
			int a = sc.nextInt(), b = sc.nextInt();
			matrix[a].add(b);
			matrix[b].add(a);
		}
		for (int i = 1; i < n + 1; i++) {
			if (!visited[i]) {
				dfs(i, i);
				components++;
			}
		}
		if (components == 1) {// 说明输入正常
			Queue<Integer> queue = new LinkedList<Integer>();
			ArrayList<Integer> list = new ArrayList<Integer>();
			queue.add(1);
			initVisited(visited);
			visited[1] = true;
			int max = getDeep(queue, 1);
			// 找到最远节点,加入到list中
			for (int i = 1; i < n + 1; i++){
				if (deep[i] == max){
					list.add(i);
				}
			}
			initVisited(visited);
			max = list.get(0);
			visited[max] = true;
			queue.add(max);
			max = getDeep(queue, max);
			for (int i = 1; i < n + 1; i++){
				if (deep[i] == max && !list.contains(i)){
					list.add(i);
				}
			}
			Collections.sort(list);
			for (Integer v : list)
				System.out.println(v);

		} else {
			System.out.println("Error: " + components + " components");
		}
		sc.close();
	}

	/*
	 * 获得当前树的最深深度
	 */
	private static int getDeep(Queue<Integer> queue, int end) {
		int level = 1;
		int tmpEnd=end;
		while (!queue.isEmpty()) {
			int tmp = queue.poll();
			for (Integer v : matrix[tmp]) {
				if (!visited[v]) {
					deep[v] = level;
					queue.offer(v);
					visited[v] = true;
					tmpEnd=v;
				}
			}
			if (!queue.isEmpty()&&tmp == end) {
				end = tmpEnd;
				level++;
			}
		}
		return level-1;
	}

	/*
	 * 初始化visited矩阵(设置为false)
	 */
	private static void initVisited(boolean[] visited2) {
		for (int i = 1; i < n + 1; i++)
			visited[i] = false;
	}

	/*
	 * 深度优先搜索
	 */
	private static void dfs(int root, int pre) {
		visited[root] = true;
		for (Integer temp : matrix[root]) {
			if (temp.equals(pre))
				continue;
			if (!visited[temp])
				dfs(temp, root);
		}
	}
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值