hdu 3534 树形dp ***

题意:统计一棵带权树上两点之间的最长距离以及最长距离的数目

链接:点我

首先统计出结点到叶子结点的最长距离和次长距离。

然后找寻经过这个点的,在这个为根结点的子树中的最长路径个数目。

  1 #include <string.h>
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <stdio.h>
  5 using namespace std;
  6 const int MAXN=100010;
  7 const int INF=0x3f3f3f3f;
  8 struct Node
  9 {
 10     int to,next,len;
 11 }edge[MAXN*2];
 12 int head[MAXN];
 13 int tol;
 14 int maxn[MAXN];//该节点往下到叶子结点的最大距离
 15 int smaxn[MAXN];// 次大距离
 16 int maxn_num[MAXN];//最大距离的个数
 17 int smaxn_num[MAXN];//次大距离的个数
 18 int path[MAXN];//该结点为根的子树中,包含该结点的最长路径长度
 19 int num[MAXN];//最长路径的长度
 20 
 21 void init()
 22 {
 23     tol=0;
 24     memset(head,-1,sizeof(head));
 25 }
 26 void add(int u,int v,int w)
 27 {
 28     edge[tol].to=v;
 29     edge[tol].len=w;
 30     edge[tol].next=head[u];
 31     head[u]=tol++;
 32     edge[tol].to=u;
 33     edge[tol].len=w;
 34     edge[tol].next=head[v];
 35     head[v]=tol++;
 36 }
 37 
 38 void dfs(int u,int pre)
 39 {
 40     maxn[u]=smaxn[u]=0;
 41     maxn_num[u]=smaxn_num[u]=0;
 42     for(int i=head[u];i!=-1;i=edge[i].next)
 43     {
 44         int v=edge[i].to;
 45         if(v==pre)continue;
 46         dfs(v,u);
 47         if(maxn[v]+edge[i].len>maxn[u])
 48         {
 49             smaxn[u]=maxn[u];
 50             smaxn_num[u]=maxn_num[u];
 51             maxn[u]=maxn[v]+edge[i].len;
 52             maxn_num[u]=maxn_num[v];
 53         }
 54         else if(maxn[v]+edge[i].len==maxn[u])
 55         {
 56             maxn_num[u]+=maxn_num[v];
 57         }
 58         else if(maxn[v]+edge[i].len>smaxn[u])
 59         {
 60             smaxn[u]=maxn[v]+edge[i].len;
 61             smaxn_num[u]=maxn_num[v];
 62         }
 63         else if(maxn[v]+edge[i].len==smaxn[u])
 64         {
 65             smaxn_num[u]+=maxn_num[v];
 66         }
 67     }
 68     if(maxn_num[u]==0)//叶子结点
 69     {
 70         maxn[u]=smaxn[u]=0;
 71         maxn_num[u]=smaxn_num[u]=1;
 72         path[u]=0;
 73         num[u]=1;
 74         return;
 75     }
 76     //到这里已经统计出了u节点到叶子的最长和次长
 77     int c1=0,c2=0;
 78     for(int i=head[u];i!=-1;i=edge[i].next)
 79     {
 80         int v=edge[i].to;
 81         if(v==pre)continue;
 82         if(maxn[u]==maxn[v]+edge[i].len)c1++;
 83         else if(smaxn[u]==maxn[v]+edge[i].len)c2++;
 84     }
 85     path[u]=0;
 86     num[u]=0;
 87     if(c1>=2)//最长+最长
 88     {
 89         int tmp=0;
 90         path[u]=maxn[u]*2;
 91         for(int i=head[u];i!=-1;i=edge[i].next)
 92         {
 93             int v=edge[i].to;
 94             if(v==pre)continue;
 95             if(maxn[u]==maxn[v]+edge[i].len)
 96             {
 97                 num[u]+=tmp*maxn_num[v];
 98                 tmp+=maxn_num[v];
 99             }
100         }
101     }
102     else if(c1>=1 && c2>=1)//最长+次长
103     {
104         path[u]=maxn[u]+smaxn[u];
105         for(int i=head[u];i!=-1;i=edge[i].next)
106         {
107             int v=edge[i].to;
108             if(v==pre)continue;
109             if(maxn[u]==maxn[v]+edge[i].len)
110             {
111                 num[u]+=maxn_num[v]*smaxn_num[u];
112             }
113         }
114     }
115     else//最长
116     {
117         path[u]=maxn[u];
118         num[u]=maxn_num[u];
119     }
120 }
121 int main()
122 {
123     int n;
124     while(scanf("%d",&n)==1)
125     {
126         int u,v,w;
127         init();
128         for(int i=1;i<n;i++)
129         {
130             scanf("%d%d%d",&u,&v,&w);
131             add(u,v,w);
132         }
133         dfs(1,-1);
134         int ans1=0,ans2=0;
135         for(int i=1;i<=n;i++)
136         {
137             if(path[i]>ans1)
138             {
139                 ans1=path[i];
140                 ans2=num[i];
141             }
142             else if(path[i]==ans1)
143                 ans2+=num[i];
144         }
145         printf("%d %d\n",ans1,ans2);
146     }
147     return 0;
148 }

 

posted @ 2015-06-18 10:08  miao_a_miao  阅读(141)  评论(0编辑  收藏  举报