• 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
    ",ans1,ans2);
    146     }
    147     return 0;
    148 }
  • 相关阅读:
    foreach和each
    one
    存储
    动态添加
    百度描点
    php环境配置
    图文并茂
    css实现鼠标移上去变大,旋转,转别人的额
    vagrant box打包前的准备
    VirtualBox压缩打包
  • 原文地址:https://www.cnblogs.com/cnblogs321114287/p/4585090.html
Copyright © 2020-2023  润新知