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\n",maxlen[i]);
}
return 0;
}