#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdio>
#include <cstring>
using namespace std;
const int M=1e5+20;
int n;
int vis[M];
struct Node{
int v,w;
Node(int a,int b)
{
v=a;
w=b;
}
};
vector<Node> e[2*M];//双向边
long long dp[M][3];//dp[u][staus] staus=0,1,2分别表示节点u从子树得到最远距离和'次'远距离(来自u的两个不同子节点)
//从父节点处得到的最远距离
void dfs1(int u)//先求到子树的最远距离
{
int biggest=0,bigger=0;
vis[u]=1;
for(int i=0;i<e[u].size();i++)
{
int v=e[u][i].v;
int w=e[u][i].w;
if(!vis[v])
{
dfs1(v);
int tmp=dp[v][0]+e[u][i].w;//保证了来自u两个不同的子节点
if(tmp>=biggest)
{
bigger=biggest;
biggest=tmp;
}
else if(bigger<tmp)
{
bigger=tmp;
}
}
}
dp[u][0]=biggest;
dp[u][1]=bigger;
}
void dfs2(int u) // dp[u][2]=max(dp[fa][2],dp[u][0]+w==dp[fa][0]?dp[fa][1]:dp[fa][0])+w(fa,u)
//注意dp[fa][0]:维护'次'远距离就是为了 from sons of fa 时不要取到 u否则 fa->u这个状态可能不会不记录
{
vis[u]=1;
for(int i=0;i<e[u].size();i++)
{
int v=e[u][i].v;
int w=e[u][i].w;
if(!vis[v])
{
dp[v][2]=max(dp[u][2],dp[v][0]+w==dp[u][0]?dp[u][1]:dp[u][0])+w;
dfs2(v);
}
}
}
int main()
{
while(cin>>n)
{
for(int i=1;i<=n;i++)
e[i].clear();
for(int u=2;u<=n;u++)
{
int a,b;
scanf("%d%d",&a,&b);
e[u].push_back(Node(a,b));
e[a].push_back(Node(u,b));
}
memset(vis,0,sizeof(vis));
memset(dp,0,sizeof(dp));
dfs1(1);//1当作根节点
memset(vis,0,sizeof(vis));
dp[1][2]=0;
dfs2(1);
for(int i=1;i<=n;i++)
{
long long k=max(dp[i][0],dp[i][2]);
cout<<k<<endl;;
}
}
return 0;
}
hdu 2196树形dp经典 树的最长路
最新推荐文章于 2019-12-02 22:48:01 发布