Problem G
The Tree Root
Input: standard input
Output: standard output
Time Limit: 4 seconds
Tree is an important data structure. Searching is a basic operation in any data structure. In a tree searching mainly depends on its height. Consider the following three trees.
If you observe carefully, you will see that all trees are same except different nodes are used as roots. Here the height of the tree varies with the selection of the root. In the 1st tree root is '2' and height is 3. In 2nd one root is '1' and height is 2. And in last one root is '4' and height is 4. We will call '1' best root as it keeps the tree with the least possible height and '4' worst root for the opposite reason.
In this problem, you have to find out all best roots and worst roots for a given tree.
Input
Each dataset starts with a positive integer N(3<=N<=5000), which is the number of nodes in the tree. Each node in the tree has a unique id from 1 to N. Then successively for each i'th node there will be a positive integer K[i] following id of K[i] nodes which are adjacent to i. Input is terminated by EOF.
Output
For each dataset print two lines. In the 1st line show all the best roots in ascending order and in next line show all worst roots in ascending order. See sample output for exact format.
Sample Input
7 2 2 3 3 1 6 7 3 1 4 5 1 3 1 3 1 2 1 2
Sample Output
Best Roots : 1 Worst Roots : 4 5 6 7
Author : Md. Kamruzzaman
The Real Programmers' Contest-2
这道题要求树的“中心”,和“worst root”。所谓树的“中心”:想辦法選定一個樹根,讓樹的高度最小。
通过这题,学了一个新姿势。参考http://www.cnblogs.com/wally/p/3311768.html。
先问这样一个问题:求树上每个节点到树上其他节点的最远距离。解法:因为可以证明树上任意某个节点到树上任意节点的最远距离的端点一定会是树上直径的两个端点之一。所以只需要找出任意一对直径的两个端点,分别以它们为根求到其他点的距离,并更新每个点的最远距离。具体做法就是先任意一次dfs求出树上最长直径的一个端点End,然后以该端点为起点再次dfs求出另一个端点,然后再次以求出的另一个端点为起点dfs,每次做dfs的时候都更新dist[](dist[u]表示u到树上任意节点的最远距离)。
对这个题来说,有了dist数组后,dist最小的点对应的就是中心(当直径长度为偶数时,有两个),最远的dist是直径,对应的点是worst root。至此,题目解决。
#include<cstdio> #include<map> #include<queue> #include<cstring> #include<iostream> #include<algorithm> #include<vector> #include<list> #include<set> #include<cmath> using namespace std; const int maxn = 5000 + 5; const int INF = 1000000000; const double eps = 1e-6; typedef unsigned long long ULL; typedef long long LL; typedef pair<int, int> P; #define fi first #define se second vector<int> G[maxn]; int dis[maxn]; int e, maxd; void dfs(int now, int fa, int dep){ dis[now] = max(dis[now], dep); if(dis[now] > maxd){//当maxd更新的时候,更改直径的端点e maxd = dis[now]; e = now; } for(int i = 0;i < G[now].size();i++){ int to = G[now][i]; if(to != fa) dfs(to, now, dep+1); } } int main(){ int n; while(scanf("%d", &n) != EOF){ for(int i = 1;i <= n;i++){ G[i].clear(); int num, x; scanf("%d", &num); while(num--){ scanf("%d", &x); G[i].push_back(x); } } memset(dis, 0, sizeof dis); e = 1, maxd = 0; dfs(e, 0, -1); dfs(e, 0, -1); dfs(e, 0, -1); int mind = INF; for(int i = 1;i <= n;i++) mind = min(mind, dis[i]); printf("Best Roots :"); for(int i = 1;i <= n;i++){ if(dis[i]==mind) printf(" %d", i); } puts(""); printf("Worst Roots :"); for(int i = 1;i <= n;i++){ if(dis[i]==maxd) printf(" %d", i); } puts(""); } return 0; } /* 3 1 2 2 1 3 1 2 */