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;
}


 


 

posted on 2013-07-31 19:42  you Richer  阅读(206)  评论(0编辑  收藏  举报