题目传送门

题意:给出一个有$N$个点的树,你最开始在$1$号点,经过第$i$条边需要花费$w_i$的时间。每条边只能被经过$2$次。求出到达除$1$号点外所有点的最早时间的最小平均值。$N \leq 10^5 , w \leq 1000$


设$f_i$表示以第$i$个点为子树的最小总时间,考虑由儿子向父亲合并,额外定义$dis_i$为$i$到其父亲的边的边权,$t_i$表示从$t$的父亲走完根节点为$t$的子树再回到$t$的时间,也就等于$(\text{子树边权和+与父亲相连的边的边权})\times 2$,再定义$size_i$表示以$i$为根节点的子树的点数。可以$t_i$与$size_i$都是很容易从儿子向父亲合并的。

设我们正在算点$x$的答案,其儿子为$y_1,y_2...y_k$,且它们的答案已经算出来了。那么它的父亲的答案也就是$\sum\limits_{i=1}^k (f_{y_i}+dis_i \times size_i) + \sum\limits_{i=1}^k t_{p_i} \times (size_x - 1 - \sum\limits_{j=1}^i size_{p_i})$,其中$p_1,p_2...p_k$是一个$y_1,y_2...y_k$的排列,因为子树的选择是无序的,而在选择某个子树的时候,剩下没有选的所有点都需要等待这棵子树遍历完。

那么现在我们的任务转变为了找到一个最优的$p_1,p_2...p_k$的选择。考虑这个排列可能与排序有关,所以我们使用邻项交换的方法分析是否具有贪心策略。考虑相邻两个元素$p_i,p_i+1$,因为交换对于其他元素的答案是没有影响的,所以我们只需要考虑$p_i$与$p_{i+1}$的差别,将其他的设为$W$。

当我们的顺序是$p_i,p_{i+1}$时,答案是$f_{p_i}+t_{p_i} \times size_{p_{i+1}}+f_{p_{i+1}}+W$,而当顺序为$p_{i+1},p_i$时答案为$f_{p_{i+1}}+t_{p_{i+1}} \times size_{p_i}+f_{p_i}+W$。我们令第一种方案优于第二种方案,所以$f_{p_i}+t_{p_i} \times size_{p_{i+1}}+f_{p_{i+1}}+W < f_{p_{i+1}}+t_{p_{i+1}} \times size_{p_i}+f_{p_i}+W$,可以得到$t_{p_i} \times size_{p_{i+1}} < t_{p_{i+1}} \times size_{p_i}$。所以我们使用这个公式进行排序,就可以得到最优的方案。

 #include<bits/stdc++.h>
 #define ld long double
 #define MAXN 500010
 #define int long long
 using namespace std;

 inline int read(){
     ;
     ;
     char c = getchar();
     while(!isdigit(c)){
         if(c == '-')
             f = ;
         c = getchar();
     }
     while(isdigit(c)){
         a = (a << ) + (a << ) + (c ^ ');
         c = getchar();
     }
     return f ? -a : a;
 }

 struct Edge{
     int end , upEd , w;
 }Ed[MAXN];
 int head[MAXN] , siz[MAXN] , T[MAXN] , N , cntEd , forC;
 ld dp[MAXN];

 bool cmp(int a , int b){
     return T[a] * siz[b] < T[b] * siz[a];
 }

 inline void addEd(int a , int b , int c){
     Ed[++cntEd].end = b;
     Ed[cntEd].upEd = head[a];
     Ed[cntEd].w = c;
     head[a] = cntEd;
 }

 void dfs(int now){
     siz[now] = ;
     vector < int > v;
     for(int i = head[now] ; i ; i = Ed[i].upEd)
         if(!siz[Ed[i].end]){
             dfs(Ed[i].end);
             siz[now] += siz[Ed[i].end];
             T[Ed[i].end] += Ed[i].w << ;
             dp[Ed[i].end] += Ed[i].w * siz[Ed[i].end];
             v.push_back(Ed[i].end);
         }
     sort(v.begin() , v.end() , cmp);
      ; i < v.size() ; i++){
         dp[now] += T[now] * siz[v[i]] + dp[v[i]];
         T[now] += T[v[i]];
     }
 }
 main(){
     N = read();
      ; i < N ; i++){
         int a = read() , b = read() , c = read();
         addEd(a , b , c);
         addEd(b , a , c);
     }
     dfs();
     cout << ) << dp[] * );
     ;
 }

CF101D Castle 树形DP、贪心的更多相关文章

  1. 【bzoj4027】[HEOI2015]兔子与樱花 树形dp+贪心

    题目描述 很久很久之前,森林里住着一群兔子.有一天,兔子们突然决定要去看樱花.兔子们所在森林里的樱花树很特殊.樱花树由n个树枝分叉点组成,编号从0到n-1,这n个分叉点由n-1个树枝连接,我们可以把它 ...

  2. [BZOJ1596] [Usaco2008 Jan]电话网络(树形DP || 贪心)

    传送门 1.树形DP #include <cstdio> #include <cstring> #include <iostream> #define N 1000 ...

  3. bzoj 3829: [Poi2014]FarmCraft 树形dp+贪心

    题意: $mhy$ 住在一棵有 $n$ 个点的树的 $1$ 号结点上,每个结点上都有一个妹子. $mhy$ 从自己家出发,去给每一个妹子都送一台电脑,每个妹子拿到电脑后就会开始安装 $zhx$ 牌杀毒 ...

  4. 树形DP+贪心(乱搞)(HDU4714)

    题意:给出一个树形图,要求把该树形成一个环最少的步骤(断开一条边和形成一条边都需一步) 分析:很明显,要想把树形成一个环,就要先把其分裂成m条子链之后把子链形成环需要的步骤是2*m+1,所以只需要m最 ...

  5. [HNOI2003]消防局的设立 树形dp // 贪心

    https://www.luogu.org/problemnew/show/P2279 一开始就想到了贪心的方法,不过一直觉得不能证明. 贪心的考虑是在深度从深到浅遍历每个结点的过程中,对于每个没有覆 ...

  6. POJ - 2057 The Lost House(树形DP+贪心)

    https://vjudge.net/problem/POJ-2057 题意 有一只蜗牛爬上某个树枝末睡着之后从树上掉下来,发现后面的"房子"却丢在了树上面,.现在这只蜗牛要求寻找 ...

  7. [POI2014]FAR-FarmCraft 树形DP + 贪心思想

    (感觉洛谷上题面那一小段中文根本看不懂啊,好多条件都没讲,直接就是安装也要一个时间啊,,,明明不止啊!还好有百度翻译......) 题意:一棵树,一开始在1号节点(root),边权都为1,每个点有点权 ...

  8. ACM学习历程—FZU2195 检查站点(树形DP || 贪心)

    Description 在山上一共有N个站点需要检查,检查员从山顶出发去各个站点进行检查,各个站点间有且仅有一条通路,检查员下山前往站点时比较轻松,而上山时却需要额外的时间,问最后检查员检查完所有站点 ...

  9. BZOJ4027/LG4107 「HEOI2015」兔子与樱花 树形DP+贪心

    问题描述 LG4107 题解 首先,我们可以直接令结点 \(x\) 的权值为 \(c[x]+son_x\) ,发现将 \(x,y\) 合并,相当于增加 \(c[x]+c[y]-1\) 的重量. 容易想 ...

随机推荐

  1. 为什么radio没有出现单选效果?

    原因是radio一定要设置相同的name,如下: <input type="radio" name="yunsuan" checked="che ...

  2. JMeter 扩展JMeter插件获取更多监听器

    扩展Jmeter插件获取更多监听器 by:授客 QQ:1033553122 为了获取更多监听器,方便的监控系统及应用,有必要安装第三方插件. 插件下载地址: https://jmeter-plugin ...

  3. 测试思想-流程规范 SVN代码管理与版本控制

    SVN代码管理与版本控制 by:授客 QQ:1033553122   欢迎加入软件性能测试交流群(QQ群):7156436   目录 一. 二. 三. 四. 五. 六. 七. 一. 创建根目录 创建一 ...

  4. 使用volley上传多张图片,一个参数对应多张图片,转载

    https://my.oschina.net/u/1177694/blog/491834 原帖地址 而如果使用volley的话,因为请求数据那些都很简便,但遇到上传文件就麻烦那可不好,同时使用多个网络 ...

  5. 【详细】【转】C#中理解委托和事件

    文章是很基础,但很实用,看了这篇文章,让我一下回到了2016年刚刚学委托的时候,故转之! 1.委托 委托类似于C++中的函数指针(一个指向内存位置的指针).委托是C#中类型安全的,可以订阅一个或多个具 ...

  6. python 定时修改数据库

    当需要定时修改数据库时,一般我们都选择起一个定时进程去改库.如果将这种定时任务写入业务中,写成一个接口呢,定时进程显得有些不太合适?如果需要定时修改100次数据库,常规做法会启动100个进程,虽然这种 ...

  7. LeetCode题解之Binary Tree Level Order Traversal II

    1.题目描述 2.题目分析 先遍历,再反转. 3.代码 vector<vector<int>> levelOrderBottom(TreeNode* root) { vecto ...

  8. python基础知识回顾之字符串

    字符串是python中使用频率很高的一种数据类型,内置方法也是超级多,对于常用的方法,还是要注意掌握的. #author: Administrator #date: 2018/10/20 # pyth ...

  9. 05LaTeX学习系列之---TeX的命令行操作

    目录 目录 前言 (一)查看版本号 1.查看TeX的版本号 2.查看LaTeX的版本号 3.查看XeLeTeX的版本号 (二)更行版本 (三)用命令行来编译.tex文件 1.用LaTeX编译 2.用X ...

  10. ELK-elasticsearch-6.3.2部署

    参考博客:linux下ElasticSearch.6.2.2集群安装与head.Kibana.X-Pack..插件的配置安装 参考博客:ELK5.5.1 插件安装实践纪要(head/bigdesk/k ...