题意
hdu2196
求树上每个点能到达的最远距离
题解
呜呜呜网上说是..基础题【捂脸】
下面说正题…
每个点能到达的最远距离无非两种,一种向下一直走到底,一种向上走一段在下到底
因此对于每一个点记录
表示子树中最远距离;
表示子树中次远距离;
表示通过父节点向上的那条最远路径
至于转移,用一次dfs可以求出
再用一次dfs求出
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 11000
int n,num=0,dp[N][3],d[N],h[N],mx[N];
struct node{int x,y,z,next;}mp[2*N];
//dp[i][0]表示子树最远距离
//dp[i][1]表示子树次远距离
//dp[i][2]表示从父节点来的最远距离
void insert(int x,int y,int z){
mp[++num].x=x;mp[num].y=y;mp[num].z=z;mp[num].next=h[x];h[x]=num;
mp[++num].x=y;mp[num].y=x;mp[num].z=z;mp[num].next=h[y];h[y]=num;
}
void dfs1(int u){
dp[u][0]=0;dp[u][1]=0;
for(int i=h[u];i;i=mp[i].next){
int v=mp[i].y;
if(!d[v]){
d[v]=d[u]+1;dfs1(v);
if(dp[v][0]+mp[i].z>=dp[u][0]) dp[u][1]=dp[u][0],dp[u][0]=dp[v][0]+mp[i].z,mx[u]=v;
else if(dp[v][0]+mp[i].z>dp[u][1]) dp[u][1]=dp[v][0]+mp[i].z;
else if(dp[v][1]+mp[i].z>dp[u][1]) dp[u][1]=dp[v][1]+mp[i].z;
}
}
}
void dfs2(int u){
for(int i=h[u];i;i=mp[i].next){
int v=mp[i].y;
if(d[v]==d[u]+1){
if(mx[u]==v) dp[v][2]=max(dp[u][1],dp[u][2])+mp[i].z;
else dp[v][2]=max(dp[u][2],dp[u][0])+mp[i].z;
dfs2(v);
}
}
}
int main(){
while(scanf("%d",&n)>0){
memset(h,0,sizeof(h)); num=0;
memset(d,0,sizeof(d));
memset(dp,0,sizeof(dp));
memset(mx,0,sizeof(mx));
for(int i=2;i<=n;i++){
int x,y;scanf("%d%d",&x,&y);
insert(i,x,y);
}d[1]=1;dfs1(1);dfs2(1);
for(int i=1;i<=n;i++) printf("%d\n",max(dp[i][0],dp[i][2]));
}
return 0;
}