題意:給定一棵樹,求每一個節點所能到達的最長路徑的長度
分析:以編號的i的節點為例(非根節點),最長的路徑長度只有倆種可能,1)子樹中存在最長路徑;2)通過父節點的路徑中存在最長路徑
所以,只有分別求出每一節點對應的那倆種路徑取大最大值即可,當然,根節點只存在第一種可能
View Code
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
using namespace std;
const int N = 10010;
int n,dist[N],dp[N];
struct edge
{
int v,w,h;
edge(){}
edge(int a,int b,int c=0):v(a),w(b),h(c){}
};
struct node
{
int w,id;
node(){}
node(int a,int b):w(a),id(b){}
};
vector<edge> g[N];
void init()
{
for(int i=0;i<=n;i++)
g[i].clear();
}
void dfs1(int u)
{
int size=g[u].size();
dist[u]=0;
node mdis1=node(0,0),mdis2=node(0,0);
//mdis1和mdis2 分別記錄u的子樹中的最長路徑長度,以及所在的分支編號
for(int i=0;i<size;i++)
{
int v=g[u][i].v;
dfs1(v);
node t=node(g[u][i].w+dist[v],i);
if(t.w>mdis1.w)
{
mdis2=mdis1;
mdis1=t;
}
else if(t.w>mdis2.w)
mdis2=t;
}
dist[u]=mdis1.w;
for(int i=0;i<size;i++)
{
if(i==mdis1.id)
g[u][i].h=mdis2.w;//記錄子樹中,第i的兒子所在分支以外的最長路徑
else g[u][i].h=mdis1.w;
}
}
void dfs2(int u)
{
int size=g[u].size();
for(int i=0;i<size;i++)
{
int v=g[u][i].v;
if(u==1)
{
dp[v]=g[u][i].h+g[u][i].w;
}
else {
dp[v]=max(dp[u],g[u][i].h)+g[u][i].w;//儲存通過父親節點的路徑的最大長度
}
dfs2(v);
}
}
int main()
{
int x,w;
while(scanf("%d",&n)==1)
{
init();
for(int i=2;i<=n;i++)
{
scanf("%d %d",&x,&w);
g[x].push_back(edge(i,w,0));
}
dfs1(1);
memset(dp,0,sizeof(dp));
dp[1]=dist[1];
dfs2(1);
for(int i=1;i<=n;i++)
printf("%d\n",max(dp[i],dist[i]));
}
return 0;
}