hdu 2196 (树形DP)
求出每一点到所有点的最大距离,刚开始就有点想法求最长边的问题,但想了一会不知道怎么去把子节点转化成根节点。
任选一点为根节点,先求出每个节点到子节点的最大距离和次大距离,然后更新每个子节点的最大,次大距离,就是把每个子节点当一次根节点,如果它在父节点的最大距离边上,就用次大距离+到父节点的距离与自己的最大次大距离比较,,,,
#include<stdio.h> #include<string.h> #define N 10001 int n,head[N],num,vis[N],dp[N][2]; struct edge { int st,ed,next,w; }E[N*2]; void addedge(int x,int y,int w) { E[num].st=x; E[num].ed=y; E[num].w=w; E[num].next=head[x]; head[x]=num++; } int dfs(int u) { int i,v; vis[u]=1; for(i=head[u];i!=-1;i=E[i].next) { v=E[i].ed; if(vis[v]==1)continue; int temp=dfs(v)+E[i].w; if(temp>dp[u][1])//最长边 { dp[u][0]=dp[u][1]; dp[u][1]=temp; } else if(temp>dp[u][0])//次长边 { dp[u][0]=temp; } } return dp[u][1]; } void dfs1(int u) { vis[u]=1; int i,v,temp; for(i=head[u];i!=-1;i=E[i].next) { v=E[i].ed; if(vis[v]==1)continue; if(dp[v][1]+E[i].w==dp[u][1])//如果改点在父节点的最长边上,就与次长边比较 temp=dp[u][0]+E[i].w; else temp=dp[u][1]+E[i].w;//不在父节点的最长边上,就与最长边比较 if(temp>dp[v][1]) { dp[v][0]=dp[v][1]; dp[v][1]=temp; } else if(temp>dp[v][0]) { dp[v][0]=temp; } dfs1(v); } } int main() { int i,x,y,w; while(scanf("%d",&n)!=-1) { memset(head,-1,sizeof(head)); num=0; for(x=2;x<=n;x++) { scanf("%d%d",&y,&w); addedge(x,y,w); addedge(y,x,w); } memset(dp,0,sizeof(dp)); memset(vis,0,sizeof(vis)); dfs(1); memset(vis,0,sizeof(vis)); dfs1(1); for(i=1;i<=n;i++) printf("%d\n",dp[i][0]>dp[i][1]?dp[i][0]:dp[i][1]); } return 0; }