题目
题目链接:https://gmoj.net/senior/#main/show/4279
有一棵 (n) 个点的无向树,每个点的编号在 (1sim n) 之间,求出每个点所在的最长路。
思路
先用 dp 求出每个点到其子树内路径长度最大值和其子树内最长路。
然后再次搜索每一个点,同时枚举其兄弟节点更新从子树外部连接到这一个点的最长路径。更新答案即可。
时间复杂度 (O(n))。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=100010;
int n,tot,f[N],head[N],maxl[N];
struct edge
{
int next,to,dis;
}e[N*2];
void add(int from,int to,int dis)
{
e[++tot].to=to;
e[tot].dis=dis;
e[tot].next=head[from];
head[from]=tot;
}
void dfs1(int x,int fa)
{
for (int i=head[x];~i;i=e[i].next)
{
int v=e[i].to;
if (v!=fa)
{
dfs1(v,x);
maxl[x]=max(maxl[x],f[x]+f[v]+e[i].dis);
f[x]=max(f[x],f[v]+e[i].dis);
}
}
}
void dfs2(int x,int fa,int dis)
{
for (int i=head[x];~i;i=e[i].next)
{
int v=e[i].to,maxd=dis;
if (v!=fa)
{
for (int j=head[x];~j;j=e[j].next)
if (e[j].to!=fa && e[j].to!=v)
maxd=max(maxd,f[e[j].to]+e[j].dis);
maxl[v]=max(maxl[v],maxd+e[i].dis+f[v]);
dfs2(v,x,maxd+e[i].dis);
}
}
}
int main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
memset(head,-1,sizeof(head));
scanf("%d",&n);
for (int i=1,x,y,z;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z); add(y,x,z);
}
dfs1(1,0); dfs2(1,0,0);
for (int i=1;i<=n;i++)
printf("%d
",maxl[i]);
return 0;
}