题目链接:https://vjudge.net/problem/HDU-6446

题意:简化题意后就是求距离和的2*(n-1)!倍。

思路:

  简单的树形dp,通过求每条边的贡献计算距离和,边(u,v)的贡献为sz[v]*(n-sz[v])。

  1. #include<cstdio>
  2. #include<algorithm>
  3. using namespace std;
  4.  
  5. typedef long long LL;
  6. const int maxn=1e5+;
  7. const int MOD=1e9+;
  8. int n,cnt,head[maxn],sz[maxn];
  9. LL ans;
  10.  
  11. struct node{
  12. int v,nex;
  13. LL w;
  14. }edge[maxn<<];
  15.  
  16. void adde(int u,int v,LL w){
  17. edge[++cnt].v=v;
  18. edge[cnt].w=w;
  19. edge[cnt].nex=head[u];
  20. head[u]=cnt;
  21. }
  22.  
  23. void dfs(int u,int fa){
  24. sz[u]=;
  25. for(int i=head[u];i;i=edge[i].nex){
  26. int v=edge[i].v;
  27. if(v==fa) continue;
  28. dfs(v,u);
  29. sz[u]+=sz[v];
  30. ans=(ans+edge[i].w*sz[v]%MOD*(n-sz[v])%MOD)%MOD;
  31. }
  32. }
  33.  
  34. int main(){
  35. while(~scanf("%d",&n)){
  36. ans=;
  37. cnt=;
  38. for(int i=;i<=n;++i)
  39. head[i]=;
  40. for(int i=;i<n;++i){
  41. int u,v;LL w;
  42. scanf("%d%d%lld",&u,&v,&w);
  43. adde(u,v,w);
  44. adde(v,u,w);
  45. }
  46. dfs(,);
  47. for(int i=;i<n;++i)
  48. ans=ans*i%MOD;
  49. ans=ans*%MOD;
  50. printf("%lld\n",ans);
  51. }
  52. return ;
  53. }

  另外因为前几天学点分治,看到这题想到可以用点分治求距离和。具体做法是,通过求得重心u后求所有点到重心的距离dis[i],然后采用点分治的第二种写法,遍历u的所有子结点v,用sum表示前面计算过的距离总和,num表示前面的结点数,那么对当前遍历的dis[i],其贡献为num*dis[i]+sum。但要注意不要漏了以重心为端点的边,所以将num初始化1,而不是0。

  点分治代码:

  1. #include<cstdio>
  2. #include<algorithm>
  3. using namespace std;
  4.  
  5. typedef long long LL;
  6. const int maxn=1e5+;
  7. const int MOD=1e9+;
  8. const int inf=0x3f3f3f3f;
  9. int n,cnt,head[maxn],sz[maxn],mson[maxn],Min,size,root;
  10. int vis[maxn],t,num;
  11. LL dis[maxn],tmp,sum,ans;
  12.  
  13. struct node{
  14. int v,nex;
  15. LL w;
  16. }edge[maxn<<];
  17.  
  18. void adde(int u,int v,LL w){
  19. edge[++cnt].v=v;
  20. edge[cnt].w=w;
  21. edge[cnt].nex=head[u];
  22. head[u]=cnt;
  23. }
  24.  
  25. void getroot(int u,int fa){
  26. sz[u]=,mson[u]=;
  27. for(int i=head[u];i;i=edge[i].nex){
  28. int v=edge[i].v;
  29. if(vis[v]||v==fa) continue;
  30. getroot(v,u);
  31. sz[u]+=sz[v];
  32. mson[u]=max(mson[u],sz[v]);
  33. }
  34. mson[u]=max(mson[u],size-sz[u]);
  35. if(mson[u]<Min) Min=mson[u],root=u;
  36. }
  37.  
  38. void getdis(int u,int fa,LL len){
  39. dis[++t]=len;
  40. for(int i=head[u];i;i=edge[i].nex){
  41. int v=edge[i].v;
  42. if(vis[v]||v==fa) continue;
  43. getdis(v,u,(len+edge[i].w)%MOD);
  44. }
  45. }
  46.  
  47. void solve(int u){
  48. sum=;
  49. num=;
  50. for(int i=head[u];i;i=edge[i].nex){
  51. int v=edge[i].v;
  52. if(vis[v]) continue;
  53. t=;
  54. tmp=;
  55. getdis(v,u,edge[i].w);
  56. for(int i=;i<=t;++i){
  57. ans=(ans+num*dis[i]%MOD+sum)%MOD;
  58. tmp=(tmp+dis[i])%MOD;
  59. }
  60. sum=(sum+tmp)%MOD;
  61. num+=t;
  62. }
  63. }
  64.  
  65. void fenzhi(int u,int ssize){
  66. vis[u]=;
  67. solve(u);
  68. for(int i=head[u];i;i=edge[i].nex){
  69. int v=edge[i].v;
  70. if(vis[v]) continue;
  71. Min=inf,root=;
  72. size=sz[v]<sz[u]?sz[v]:(ssize-sz[u]);
  73. getroot(v,);
  74. fenzhi(root,size);
  75. }
  76. }
  77.  
  78. int main(){
  79. while(~scanf("%d",&n)){
  80. cnt=;
  81. ans=;
  82. for(int i=;i<=n;++i)
  83. head[i]=vis[i]=;
  84. for(int i=;i<n;++i){
  85. int u,v;LL w;
  86. scanf("%d%d%lld",&u,&v,&w);
  87. adde(u,v,w);
  88. adde(v,u,w);
  89. }
  90. Min=inf,root=,size=n;
  91. getroot(,);
  92. fenzhi(root,n);
  93. for(int i=;i<n;++i)
  94. ans=ans*i%MOD;
  95. ans=ans*%MOD;
  96. printf("%lld\n",ans);
  97. }
  98. return ;
  99. }

hdoj6446(树形DP)的更多相关文章

  1. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

  2. COGS 2532. [HZOI 2016]树之美 树形dp

    可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...

  3. 【BZOJ-4726】Sabota? 树形DP

    4726: [POI2017]Sabota? Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 128  Solved ...

  4. 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)

    题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...

  5. 树形DP

    切题ing!!!!! HDU  2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...

  6. BZOJ 2286 消耗战 (虚树+树形DP)

    给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...

  7. POJ2342 树形dp

    原题:http://poj.org/problem?id=2342 树形dp入门题. 我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式 ...

  8. hdu1561 The more, The Better (树形dp+背包)

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1561 思路:树形dp+01背包 //看注释可以懂 用vector建树更简单. 代码: #i ...

  9. bzoj2500: 幸福的道路(树形dp+单调队列)

    好题.. 先找出每个节点的树上最长路 由树形DP完成 节点x,设其最长路的子节点为y 对于y的最长路,有向上和向下两种情况: down:y向子节点的最长路g[y][0] up:x的次长路的g[x][1 ...

随机推荐

  1. linux系统编程--信号

    信号的概念 man 7 siganl  查看man手册 信号在我们的生活中随处可见, 如:古代战争中摔杯为号:现代战争中的信号弹:体育比赛中使用的信号枪......他们都有共性:1. 简单 2. 不能 ...

  2. sudo/su

    linux用户分为根用户/ 普通用户 系统用户 根用户和普通用户是可以实际登录到系统中的,普通用户是没办法使用useradd添加新用户的,只有根用户有权限 当然,也可以使用su su 是切换用户的意思 ...

  3. 近期将要学习的内容(flag)

    块状链表 左偏树 最大流,最小割 费用流 数位DP 计算几何 主席树 树套树(弃疗) 斜率优化 manacher kmp,exkmp 树链剖分 splay树(只看了理论) Trie树 线段树操作及应用 ...

  4. 【csp模拟赛1】铁路网络 (network.cpp)

    [题目描述] 在暑假来临之际,小 Z 的地理老师布置了一个暑假作业,让同学们暑假期间 了解一下 C 国的铁路发展史.小 Z 在多番查证资料后发现,C 国在铁路发展初期, 铁路网络有着一个严密规整的结构 ...

  5. jQuery系列(十一):jQuery的事件绑定和解绑

    1.绑定事件 语法: bind(type,data,fn) 描述:为每一个匹配元素的特定事件(像click)绑定一个事件处理器函数. 参数解释: type (String) : 事件类型 data ( ...

  6. DPC究竟是什么

    DPC究竟是什么 DPC是“Deferred Procedure Call”的缩写,意为推迟了的过程(函数)调用.这是因为,逻辑上应该放在中断服务程序中完成的操作并非都是那么紧迫,其中有一部分可能相对 ...

  7. linux上安装nginx详细步骤

    一.安装依赖包 yum install gcc gcc-c++ pcre-devel patch libffi-devel python-devel zlib-devel bzip2-devel op ...

  8. [vbs]脚本启动

    Set ws = CreateObject("Wscript.Shell") ws.run "cmd.exe /c start tool.exe config_tence ...

  9. Leetcode题目79.单词搜索(回溯+DFS-中等)

    题目描述: 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格.同一个单元格内的字母不允许 ...

  10. 在windows系统搭建Flutter开发环境

    开发环境搭建(Windows) 系统要求 设置FLutter镜像(非必须) 获取Flutter SDK Android开发环境设置 安装Flutter插件 系统要求 在Windows上要安装并运行Fl ...