zoukankan      html  css  js  c++  java
  • codeforces294E(树的重心的应用)

     1 /*****************************************************************************************************************************************************************************************
     2 题意:树中有N个点,从N-1条边中间去除一条边,再构建一条相同长度的边连在两个节点上,使得这N个点仍然构成一棵树.
     3 问新树种任意两个点之间距离的总和最小为多少
     4 题解:
     5     由于边的数量为5000.所以可以直接枚举边.
     6     我们枚举每条边,然后删除这条边,将树分成两个子树,把新边连接第一颗树的节点U和第二课树的节点V.
     7     我们可以发现我们以上操作可以获得的价值为:
     8     子树1中任意两点距离总和+子树2中任意两点距离总和+子树1中任意一点到U的距离和*子树2的节点数量+节点2中任意一点到V的距离和*子树1的节点数量+子树1的节点个数*子树2的几点个数*新边的边权.
     9     易知当枚举的边一定时,子树1的节点数量,子树2的节点数量,子树1中任意2点的距离和,子树2中任意2点的距离和都已经被确定了.
    10     我们要做的就是在被枚举的边一定时,找到建边的最优的位置U和V来使得 子树1中任意点到U的距离和 和 子树中任意一点到v的距离和  最小.
    11     结合重心的知识,可以发现U,V其实分别是子树1的重心和子树2的重心.   
    12 ******************************************************************************************************************************************************************************************/
    13 #include<bits/stdc++.h>
    14 using namespace std;
    15 typedef long long LL;
    16 typedef pair<int,int> pii;
    17 const int maxn = 5005;
    18 const LL INF = 0x3f3f3f3f3f3f3f3fll;
    19 int f[maxn],h[maxn],w[maxn],son[maxn];
    20 vector<pii> g[maxn];
    21 LL d[maxn],s[maxn];
    22 inline void dfs(int v, int rt){
    23     son[v] = 0, d[v] = 0, s[v] = 0;
    24     for(int i = 0; i != g[v].size(); i ++){
    25         int u = g[v][i].first;
    26         if(u==rt) continue;
    27         dfs(u, v);
    28         s[v] += s[u] + d[u]*son[v] + d[v]*son[u] + (LL)son[u] * son[v] * g[v][i].second;
    29         d[v] += d[u] + (LL)son[u] * g[v][i].second;
    30         son[v] += son[u];
    31     }
    32     son[v] ++;  s[v] += d[v];
    33 }
    34 inline void dfsw(int v,int rt,LL &minn){
    35     minn = min(d[v],minn);
    36     for (int i=0; i!=g[v].size(); ++i){
    37         int u = g[v][i] . first;
    38         if (u==rt) continue;
    39         d[u] = d[u] + (d[v]-d[u]-(LL)son[u]*g[v][i].second)+(LL)(son[v]-son[u])*g[v][i].second;
    40         son[u] = son[v];
    41         dfsw(u,v,minn);
    42     }
    43 }
    44 int main(){
    45     for (int n; scanf("%d",&n)!=EOF;){
    46         for (int i=1; i<=n; ++i)    g[i].clear();
    47         for (int i=1,x,y,z; i<n; ++i)scanf("%d%d%d",&x,&y,&z),f[i] = x,h[i] = y,w[i] = z,g[x].push_back(make_pair(y,z)),g[y].push_back(make_pair(x,z));//F[I]为第I条边的起点,H[I]为第I条边的终点,w[i]为第i条边的权值 
    48         LL ans = INF , minn = INF, sum =0;
    49         for (int i=1; i<n; ++i){
    50             minn = INF;     dfs(f[i],h[i]); dfsw(f[i],h[i],minn);
    51             sum = (n-son[f[i]])*minn + s[f[i]];  
    52             minn = INF;      dfs(h[i],f[i]); dfsw(h[i],f[i],minn);
    53             sum += (n-son[h[i]])*minn+s[h[i]] + (LL) son[f[i]]* son[h[i]] * w[i];
    54             ans = min(ans,sum);
    55         }
    56         printf("%I64d
    ",ans);
    57     }
    58     return 0; 
    59 }
    60 /***********************************************************************************************************************************************************************************************************************
  • 相关阅读:
    gRPC详解
    vue 实现无限向上滚动
    vue 封装highcharts组件
    《数据结构与算法之美》32——分治算法
    《数据结构与算法之美》31——贪心算法
    《数据结构与算法之美》30——回溯算法
    《数据结构与算法之美》29——动态规划实战
    《数据结构与算法之美》28——动态规划理论
    《数据结构与算法之美》27——初识动态规划
    《数据结构与算法之美》26——广度优先搜索与深度优先搜索
  • 原文地址:https://www.cnblogs.com/juruohx/p/7241910.html
Copyright © 2011-2022 走看看