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 }

 

你可能感兴趣的:(com)