• 树形dp--hdu 3534 Tree


    Tree

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 906    Accepted Submission(s): 268

    Problem Description
    In the Data structure class of HEU, the teacher asks one problem: How to find the longest path of one tree and the number of such longest path?
    Input
    There are several test cases. The first line of each case contains only one integer N, means there are N nodes in the tree. N-1 lines follow, each line has three integers w,v and len, indicate that there is one edge between node w and v., and the length of the edge is len.
    Output
    For each test case, output the length of longest path and its number in one line.
      
    Sample Input
    4 1 2 100 2 3 50 2 4 50 4 1 2 100 2 3 50 3 4 50
    Sample Output
    150 2 200 1
    Source

    题意:给出一颗树(n个顶点,n-1条边)


    求最长的路径,以及最长路径的条数。

    路径无非就是连接两个点直接的路。

    因为是一颗树,所以连接两个点肯定是唯一的路径。

    其实就是求两点间距离的最大值,以及这个最大值有多少个。

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

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


    ...思路参考于kuangbin博客

    代码:

      1 #include "stdio.h"  //poj 3534 Tree 树形dp
      2 #include "string.h"
      3 
      4 #define N 100100
      5 
      6 struct node
      7 {
      8     int x,y;
      9     int weight;
     10     int next;
     11 }edge[2*N];
     12 int idx,head[N];
     13 
     14 void Init()
     15 {
     16     idx = 0;
     17     memset(head,-1,sizeof(head));
     18 }
     19 
     20 void Add(int x,int y,int weight)
     21 {
     22     edge[idx].x = x;
     23     edge[idx].y = y;
     24     edge[idx].weight = weight;
     25     edge[idx].next = head[x];
     26     head[x] = idx++;
     27 }
     28 
     29 int maxn[N];  //最长距离
     30 int smaxn[N];//次长距离
     31 int maxn_num[N]; //最长距离数目
     32 int smaxn_num[N]; //次长距离数目
     33 int path[N]; //经过点i的最长距离长度
     34 int num[N]; //经过点i的最长距离数目
     35 
     36 void DFS(int x,int father)
     37 {
     38     int i,y;
     39     maxn[x] = smaxn[x] = 0;
     40     maxn_num[x] = smaxn_num[x] = 0;
     41     for(i=head[x]; i!=-1; i=edge[i].next)
     42     {
     43         y = edge[i].y;
     44         if(y==father) continue;
     45         DFS(y,x);
     46         if(maxn[x] < maxn[y]+edge[i].weight)
     47         {
     48             smaxn[x] = maxn[x];
     49             smaxn_num[x] = maxn_num[x];
     50             maxn[x] = maxn[y]+edge[i].weight;
     51             maxn_num[x] = maxn_num[y];
     52         }
     53         else if(maxn[x]==maxn[y]+edge[i].weight)
     54             maxn_num[x] += maxn_num[y];
     55         else if(smaxn[x] < maxn[y]+edge[i].weight)
     56         {
     57             smaxn[x] = maxn[y]+edge[i].weight;
     58             smaxn_num[x] = maxn_num[y];
     59         }
     60         else if(smaxn[x] == maxn[y]+edge[i].weight)
     61             smaxn_num[x] += maxn_num[y];
     62     }
     63     if(maxn_num[x]==0) //叶子节点,赋初值
     64     {
     65         maxn[x] = smaxn[x] = 0;
     66         maxn_num[x] = smaxn_num[x] = 1;
     67         path[x] = 0;
     68         num[x] = 1;
     69         return ;
     70     }
     71     int c1;  //统计以x为根节点的最长距离数目
     72     int c2;  //统计以x为根节点的次长距离数目
     73     c1 = c2 = 0;
     74     for(i=head[x]; i!=-1; i=edge[i].next)
     75     {
     76         y=edge[i].y;
     77         if(y==father) continue;
     78         if(maxn[x] == maxn[y]+edge[i].weight)
     79             c1++;
     80         else if(smaxn[x] == maxn[y]+edge[i].weight)
     81             c2++;
     82     }
     83     path[x] = 0;
     84     num[x] = 0;
     85     if(c1>=2)  
     86     {
     87         int tmp = 0;
     88         path[x] = maxn[x]*2;
     89         for(i=head[x]; i!=-1; i=edge[i].next)
     90         {
     91             y = edge[i].y;
     92             if(y==father) continue;
     93             if(maxn[x]==maxn[y]+edge[i].weight)
     94             {
     95                 num[x] += tmp*maxn_num[y];
     96                 tmp += maxn_num[y];
     97             }
     98         }
     99     }
    100     else if(c1>=1 && c2>=1)
    101     {
    102         path[x] = maxn[x]+smaxn[x];
    103         for(i=head[x]; i!=-1; i=edge[i].next)
    104         {
    105             y = edge[i].y;
    106             if(y==father) continue;
    107             if(maxn[x]==maxn[y]+edge[i].weight)
    108             {
    109                 num[x] = smaxn_num[x]*maxn_num[y];
    110             }
    111         }
    112     }
    113     else
    114     {
    115         path[x] = maxn[x];
    116         num[x] = maxn_num[x];
    117     }
    118 }
    119 
    120 int main()
    121 {
    122     int n;
    123     int i,j;
    124     int x,y,k;
    125     while(scanf("%d",&n)!=EOF)
    126     {
    127         Init();
    128         for(i=1; i<n; ++i)
    129         {
    130             scanf("%d %d %d",&x,&y,&k);
    131             Add(x,y,k);
    132             Add(y,x,k);
    133         }
    134         DFS(1,-1);
    135         int dist=0,snum=0;
    136         for(i=1; i<=n; ++i)
    137         {
    138             if(path[i]>dist)
    139             {
    140                 dist = path[i];
    141                 snum = num[i];
    142             }
    143             else if(path[i]==dist)
    144             {
    145                 snum += num[i];
    146             }
    147         }
    148         printf("%d %d
    ",dist,snum);
    149     }
    150     return 0;
    151 }



  • 相关阅读:
    重塑矩阵
    数组拆分
    最大连续1的个数
    石子游戏
    概率与期望知识总结
    洛谷 P3951 NOIP 2017 小凯的疑惑
    关于结构体的初始化
    山海经:线段树维护最大子段和
    偏序 分块+bitset
    分块练习C. interval
  • 原文地址:https://www.cnblogs.com/ruo-yu/p/4411975.html
Copyright © 2020-2023  润新知