分析:
我曾经谈过树的直径
但是只停留在理论阶段,不会实现
今天就来填这个史前巨坑
我在blog提到过:
设计状态:
f[i]表示i这棵子树中经过i的最长路径(可以经过i也可以是i作为途中一点)
g[i]表示i这棵子树中,以i为端点的最长路径
f[fa]=max(firstmax{w(fa,u)+g[u]},0)+max(secondmax{w(fa,u)+g[u]},0)
g[fa]=max{w(fa,u)+g[u]}
然而我发现如果真的按照上述的方程转移的话,就很tomato难受
我们可以简化一下状态:
f[i]表示i这棵子树中,以i为端点的最长链
g[i]表示i这棵子树中,以i为端点的次长链
这样当前点对答案的贡献就是f[i]+g[i]
复杂度:O(n)
这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=100010;
int f[N],g[N];
struct node{
int x,y,nxt,v;
};
node way[N<<1];
int st[N],tot=0,ans=0,n;
void add(int u,int w,int z)
{
tot++;
way[tot].x=u;way[tot].y=w;way[tot].v=z;way[tot].nxt=st[u];st[u]=tot;
}
void dfs(int now,int fa)
{
g[now]=0; f[now]=0;
for (int i=st[now];i;i=way[i].nxt)
if (way[i].y!=fa)
{
dfs(way[i].y,now);
int len=way[i].v+f[way[i].y];
if (len>f[now])
{
g[now]=f[now];
f[now]=len;
}
else if (len>g[now])
{
g[now]=len;
}
}
ans=max(ans,f[now]+g[now]);
}
int main()
{
scanf("%d",&n);
for (int i=1;i<n;i++)
{
int u,w,z;
scanf("%d%d%d",&u,&w,&z);
add(u,w,z);
add(w,u,z);
}
dfs(1,0);
printf("%d",ans);
return 0;
}