L2-038 病毒溯源 (25 分) Java题解 (树的深度,dfs,记录路径)

L2-038 病毒溯源 (25 分) Java题解 (树的深度,dfs,记录路径)_第1张图片

输入样例:

10
3 6 4 8
0
0
0
2 5 9
0
1 7
1 2
0
2 3 1

输出样例:

4
0 4 9 1

算法思路:

求树的从根节点开始的最长的路径,只要找到根结点的所有儿子结点为根结点的最长路径即可,找到时,记录该结点的儿子结点,两个二子结点路径相等时,找最小结点号的儿子,最后输出路径。

Java代码:

import java.io.*;
import java.util.Arrays;

public class Main {
	static StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
	public static int ini() throws IOException {
		st.nextToken();
		return (int)st.nval;
	}
	
	static int n, maxdeep;
	static final int N = 10005;
	static int []e = new int[N];
	static int []ne = new int[N];
	static int []h = new int[N];
	static int idx;
	static int []son = new int[N];
	
	
	public static void main(String[] args) throws IOException {
		int n = ini();
		Arrays.fill(h, -1);
		boolean vis[] = new boolean[n];
		Arrays.fill(son, -1);
		
		for(int i = 0; i < n; i++) {
			int k = ini();
			while(k-- > 0) {
				int t = ini();
				vis[t] = true;
				add(i, t);
			}
		}
		
		int root = 0;
		for(int i = 0; i < n; i++)   // 找根结点
			if(vis[i] == false) root = i;
		
		System.out.println(dfs(root));
		System.out.print(root);
		for(int i = son[root]; i != -1; i = son[i])
			System.out.print(" " + i);
		
	}
	
	public static int dfs(int u) {  // 返回深度,求当前根的儿子结点的最大深度
		int res = 0;
		for(int i = h[u]; i != -1; i = ne[i]) {
			int j = e[i];
			int d = dfs(j);  // 求每个儿子的深度
			if(d > res) {  // 比较每个儿子的最大深度
				res = d;  // 
				son[u] = j;  // u的儿子结点为j
			}else if(d == res) { // 深度一样时,选最小的序列号
				son[u] = Math.min(j, son[u]);
			}
		}
		return res + 1; // 递归到根结点时,加上自身的高度1
	}
	
	public static void add(int a, int b) {
		e[idx] = b;
		ne[idx] = h[a];
		h[a] = idx++;
	}
}

你可能感兴趣的:(PAT甲级,树,树形dp记录方案)