HDOJ树形DP专题之Computer

题目链接

题目大意:给定一棵树,对树中每一个结点,求其距其他结点的最远距离。

分析:最初的想法是对每个结点求一次DFS,那样的话复杂度是O(N2),由于n最大可达10000,所以这个方法肯定会超时。根据树的特殊性可知,每个结点到距其最远的结点,要么通过其儿子结点到达,要么通过其父结点到达,由此想到可用树形动态规划。具体实现时,定义状态df[k],d1[k],d2[k],分别表示结点k通过父结点能到达的最远距离,通过儿子结点能到达的最远距离,通过儿子结点能到达的第二远距离。

View Code
 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <vector>
 4 #define MAX(a,b) ((a)>(b)?(a):(b))
 5 #define N 10000
 6 using namespace std;
 7 vector<int> dep[N];
 8 int p[N],d[N],len[N],d1[N],d2[N],df[N],n,dmax;
 9 void dp()
10 {
11   int i,j,u,v,tmp;
12   memset(d1,0,sizeof(d1));
13   memset(d2,0,sizeof(d2));
14   for(i=dmax;i>=0;i--)
15   {
16     for(j=0;j<dep[i].size();j++)
17     {
18       v=dep[i][j];
19       if(i)
20       {
21         u=p[v];
22         tmp=len[v]-len[u]+d1[v];
23         if(tmp>=d1[u])  d2[u]=d1[u],d1[u]=tmp;
24         else if(tmp>=d2[u]) d2[u]=tmp;
25       }
26     }
27   }
28 }
29 int dfs(int v)
30 {
31   int u,dd;
32   u=p[v];
33   if(u==-1)  return df[v]=0;
34   if(df[v]!=-1) return df[v];
35   dd=len[v]-len[u];
36   if(dd+d1[v]==d1[u]) return df[v]=MAX(df[u]+dd,d2[u]+dd);
37   else  return df[v]=MAX(df[u]+dd,d1[u]+dd); 
38 }
39 int main()
40 {
41   int i,j,k;
42   while(~scanf("%d",&n))
43   {
44     for(i=0;i<n;i++)  dep[i].clear();
45     p[0]=-1;
46     len[0]=dmax=0;
47     for(i=1;i<n;i++)
48     {
49       scanf("%d%d",&j,&k);
50       p[i]=j-1;
51       len[i]=len[j-1]+k;
52       d[i]=d[j-1]+1;
53       dmax=MAX(dmax,d[i]);
54       dep[d[i]].push_back(i);
55     }
56     dp();
57     memset(df,-1,sizeof(df));
58     for(i=0;i<n;i++)
59     {//printf("%d %d\n",d1[i],d2[i]);
60       dfs(i);
61       printf("%d\n",MAX(MAX(d1[i],d2[i]),df[i]));
62     }
63   }
64   return 0;
65 }

 

posted @ 2012-05-02 20:35  BeatLJ  阅读(265)  评论(0编辑  收藏  举报