1021. Deepest Root (25)
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 5Sample Output 1:
3 4 5Sample Input 2:
5 1 3 1 4 2 5 3 4Sample Output 2:
Error: 2 components
用的是union-find并查集,用并查集来判断是否是树比较简单,查找最长根的话就用dfs。
我也是参考网上的博客所说的:查找最长根的时候,首先从一点进行深搜,把其中距离最远的点记录下来(可访问到所有顶点,因为已经保证是树),然后从这些最远点中任选一点再进行深度搜索,这个时候的所有最远点都是最长根,关键是第一遍dfs保存的最远点也是最长根,这个地方最难理解了,首先,若第一遍dfs后的最远根不在从1开始的同一条支路上(他们的最近公共祖先是1),这是这些点必定都会是将来的最长根这很明显,若第一遍dfs后的最远根在从1开始的同一条支路上(他们的最近公共祖先不是1记为f),则第二遍dfs时的最长根所在的dfs遍历序列必过f,所以此时的情况又可将f点看做第一种情况中的1节点类似。综上第一次与第二次dfs的合集才是最终结果。
到现在还是一只半懂,不过感觉是对的,还有就是一直有一个用例不通过。。。。。不知道该怎么进一步减小内存了,看了自己还是太弱了
测试点
测试点 | 结果 | 用时(ms) | 内存(kB) | 得分/满分 |
---|---|---|---|---|
0 | 答案正确 | 101 | 11672 | 13/13 |
1 | 答案正确 | 100 | 12052 | 2/2 |
2 | 答案正确 | 193 | 15312 | 5/5 |
3 | 内存超限 | 0/2 | ||
4 | 答案正确 | 103 | 11996 | 2/2 |
5 | 答案正确 | 98 | 12168 | 1/1 |
package p1021; import java.util.Scanner; import java.util.TreeSet; public class CopyOfMain { static int[] ancestor; static int cnt = 0, N; static boolean[][] link; static boolean[] marked; static int maxDepth = 0; static TreeSet<Integer> set = new TreeSet<Integer>(), set2 = new TreeSet<Integer>(); public static void main(String[] args) { Scanner sc = new Scanner(System.in); N = sc.nextInt(); ancestor = new int[1+N]; link = new boolean[1+N][1+N]; marked = new boolean[1+N]; for(int i=0; i<N-1; i++) { int m = sc.nextInt(); int n = sc.nextInt(); link[m][n] = true; link[n][m] = true; int f1 = getFoo(m); int f2 = getFoo(n); if(f1 != f2) { ancestor[f1] = f2; cnt ++; } } if(cnt != N - 1) { System.out.printf("Error: %d components", N-cnt); return; } marked[1] = true; dfs(1, 1); marked[1] = false; set2 = (TreeSet<Integer>) set.clone(); int newStart = 0; for(int i : set) { newStart = i; break; } marked[newStart] = true; dfs(newStart, 1); marked[newStart] = false; set2.addAll(set); for(int i : set2) System.out.println(i); } private static void dfs(int start, int depth) { if(depth > maxDepth) { set.clear(); maxDepth = depth; set.add(start); } else if(depth == maxDepth) { set.add(start); } for(int i=1; i<=N; i++) { if(link[start][i] && !marked[i]) { marked[i] = true; dfs(i, depth+1); marked[i] = false; } } } private static int getFoo(int n) { while(ancestor[n] != 0) { n = ancestor[n]; } return n; } }