zoukankan      html  css  js  c++  java
  • 树形DP--求树上任意两点间距离和

    例题:HDU2376   HDU6446(2018CCPC网络赛)

    思路:求任意两点间距离和可以转换为->路径长度乘经过路径次数的和。

    求经过次数:设这条边两端的点,被经过的次数分别为A和B,那么这条边被经过的次数就是A*B,它对总距离和的贡献就是(A*B*此边长度)。

    每条边两端点经过次数的计算,可以用一次dfs解决。

    任取一点为根,在dfs的过程中,对每个点k记录其子树包含的点数(包括其自身),设点数为sum[k],则k的父亲一侧的点数即为N-sum[k]。这个统计可以和遍历同时进行。故时间复杂度为O(n)。

    HDU2376:求完距离和,再除以总路径数N*(N-1)/2,即为最后所求

    HDU6446:根据插点排序的思路,再乘以(N-1)! * 2,即为最后所求

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 typedef long long ll;
     5 const int maxn = 500005;
     6 
     7 int sum[maxn], n;
     8 ll dp[maxn];
     9 
    10 struct Edge
    11 {
    12     int v, w;
    13     Edge(int _v = 0, int _w = 0)
    14     {
    15         v = _v;
    16         w = _w;
    17     }
    18 };
    19 vector<Edge> tree[maxn];
    20 
    21 void dfs(int cur, int father)
    22 {
    23     sum[cur] = 1;
    24     for(int i = 0; i < tree[cur].size(); i++)
    25     {
    26         int son = tree[cur][i].v;
    27         ll len = tree[cur][i].w;
    28         if(father == son)
    29             continue;
    30         dfs(son, cur);
    31         sum[cur] += sum[son];
    32         dp[cur] += dp[son] + (n-sum[son]) * sum[son] * len;
    33     }
    34 }
    35 
    36 int main()
    37 {
    38     int u, v, w, T;
    39     scanf("%d", &T);
    40     while(T--)
    41     {
    42         scanf("%d", &n);
    43         for(int i = 0; i < n; i++)
    44             tree[i].clear();
    45         memset(sum, 0, sizeof(sum));
    46         memset(dp, 0, sizeof(dp));
    47         for(int i = 0; i < n-1; i++)
    48         {
    49             scanf("%d%d%d", &u, &v, &w);
    50 
    51             tree[u].push_back(Edge(v,w));
    52             tree[v].push_back(Edge(u,w));
    53         }
    54         dfs(0, -1); //设0为根节点
    55         printf("%I64d
    ", dp[0]); //这里输出的是距离和
    56     }
    57     return 0;
    58 }
  • 相关阅读:
    Invoice Helper
    Product Helper
    Order Helper
    Case Helper
    Quote Helper
    C# 工厂模式示例
    若今生长剑浣花,生死无涯
    古代美到窒息的谎言
    C#解决微信支付Exception has been thrown by the target of an invocation(调用的目标发生了异常)的问题
    文能提笔控萝莉,转载自网上
  • 原文地址:https://www.cnblogs.com/flyuz/p/9547103.html
Copyright © 2011-2022 走看看