Description
给你一棵N(N<=10000)个节点的树,求每个点到其他点的最大距离。
Input
第一行一个数N。
接下来若干行每行两个数k,t描述一条点k到点t的边(输入数据保证无重复边)。
Output
N行每行一个数表示每个点到其他点的最大距离。
Sample Input
5
1 2
1 3
1 4
4 5
Sample Output
2
3
3
2
3
解题思路
【TREE DP】对于每个数i,记录两个值first i和second i,起点标记中点为i,终点是某个叶子结点的次短路或者最短路。两条路径i点没有公共点,在记录深点a i.
f i=max(first i,up s+1,ss);up i=max(up s+1,ss);
这里的ss代表是否i在first s的路径上,ss=second s+1,否则ss=first i+1.
HINT
(参考代码,非本人)
#include <cstdio> #include <algorithm> const int maxn=20000; int deep[maxn+10],first[maxn+10],second[maxn+10],maxlen[maxn+10],n; int pre[(maxn<<1)+10],now[maxn+10],son[maxn+10],tot,up[maxn+10]; int ins(int a,int b) { tot++; pre[tot]=now[a]; now[a]=tot; son[tot]=b; return 0; } int dfs(int u,int fa) { int j=now[u]; deep[u]=deep[fa]+1; while(j) { int v=son[j]; if(v!=fa) { dfs(v,u); if(first[v]+1>second[u]) { second[u]=first[v]+1; } if(first[v]+1>first[u]) { second[u]=first[u]; first[u]=first[v]+1; } } j=pre[j]; } return 0; } int getans(int u,int fa) { maxlen[u]=std::max(first[u],up[fa]+1); up[u]=up[fa]+1; if(first[u]+1==first[fa]) { maxlen[u]=std::max(maxlen[u],second[fa]+1); up[u]=std::max(up[u],second[fa]+1); } else { maxlen[u]=std::max(maxlen[u],first[fa]+1); up[u]=std::max(up[u],first[fa]+1); } int j=now[u]; while(j) { int v=son[j]; if(v!=fa) { getans(v,u); } j=pre[j]; } return 0; } int main() { scanf("%d",&n); for(int i=1; i<n; i++) { int a,b; scanf("%d%d",&a,&b); ins(a,b); ins(b,a); } up[0]=-1; first[0]=-1; second[0]=-1; dfs(1,0); getans(1,0); for(int i=1; i<=n; i++) { printf("%d ",maxlen[i]); } return 0; }