链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2196
https://blog.youkuaiyun.com/shuangde800/article/details/9732825
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long int64;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
const int MAXN = 10010;
struct Node
{
int v, w;
};
vector<Node>adj[MAXN];
int indeg[MAXN];
int val[MAXN];
int n, m;
int64 f[MAXN][2];
int vis[MAXN];
int64 dfs1(int u) //从自己开始
{
vis[u]=true; //标记自己
f[u][0] = 0; //自己到原点的距离初始化0;
for(int i=0;i<adj[u].size();++i)//自己到每个点的距离取最大值
{
int v = adj[u][i].v; //节点
int w = adj[u][i].w; //到节点的权值
if(vis[v]) //被标记跳过
continue;
f[u][0]=max(f[u][0],dfs1(v)+w);
//自己到原点的最大距离=自己到原点的距离节点到自己的距离加上自己到谁大
}
return f[u][0];//返回节点到自己的距离
}
void dfs2(int u, int fa_w)
{
vis[u] = true;//标记自己
int max1=0, v1, max2=0, v2; //初始化
for(int i=0; i<adj[u].size(); ++i)
{
int v=adj[u][i].v; //节点
int w=adj[u][i].w; //到节点的权值
if(vis[v])
continue; //被标记跳过
int tmp=f[v][0]+w; //距离为目标节点到叶子加上自己到节点的权值。
if(tmp>max1) //(第一次t)如果下一个子节点距离更长
{
max2=max1; //(第一次为0)赋上次值
v2=v1; //(第一次。。) 为次节点
max1=tmp; //(第一次为目标节点到叶子加上自己到节点的权值。)
v1=v; //(第一次为目标权值)
}
else if(tmp==max1||tmp>max2) //如果与次值相等或者比次值大
{
max2=tmp;//次值等于这个值 。
v2=v;//次值节点为次节点。
}
}
if(u!= 1) //如果不为根节点
{
int tmp = f[u][1];//除去子节点最长距离的子节点最长距离
int v = -1;//目标节点为-1;
if(tmp > max1)
{
max2=max1;
v2=v1;
max1=tmp;
v1=v;
}
else if(tmp==max1||tmp>max2)
{
max2=tmp;
v2=v;
}
}
for(int i=0; i<adj[u].size(); ++i)
{
int v=adj[u][i].v;
int w=adj[u][i].w;
if(vis[v])
continue;
if(v==v1)
{
f[v][1] = max2 + w;
}
else
{
f[v][1] = max1 + w;
}
dfs2(v, w);
}
}
int main()
{
while(~scanf("%d", &n) && n)
{
for(int i=1;i<=n;++i)
adj[i].clear();
for(int u=2;u<=n;++u)
{
int v,w;
scanf("%d%d", &v, &w);
adj[u].push_back((Node){v,w}); //装入目标节点,权值
adj[v].push_back((Node){u,w}); //装入自己,权值
}
memset(f, 0, sizeof(f));
memset(vis, 0, sizeof(vis));
dfs1(1);
memset(vis, 0, sizeof(vis));
dfs2(1, 0);
for(int i=1; i<=n; ++i){
cout<<max(f[i][0],f[i][1])<<endl;
}
}
return 0;
}