传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6446

本题是一个树上的问题——DFS。

一棵N个结点的树,其结点为1~N。树具有N-1条边,每一条边具有一个权值。

1~N具有N!个不同的排列,第i(1≤i≤N!)个排列记为P[i],第i个排列中的第j(1≤j≤N)个数记为P[i][j]。

对于第i个排列P[i],在树上沿最短路依次通过P[i][1]~P[i][N]。记最短路的权值和为S[i],求解:

$\sum_{i=1}^{N!} S_i \mod M$

考虑1~N间的两个不同的数u、v。在N!个排列中,v恰好为u的后继的排列数为(N-1)!。于是,若记u→v的最短路为D(u,v),则所求答案为:

$(N-1)!\:*\sum_{u\ne v}D(u,v)\mod M$

现在,考虑式:

$f(T)=\sum_{u<v}D(u,v)\cdots(*)$

接下来,考虑树的结点与边。无向树上的每一个结点都是树的割顶,每一条边都是树的桥。于是,树上的每一条边将树划分为两棵子树。考虑连接结点u、v的边:这条边将树划分为以结点u为根的子树、和以结点v为根的子树。设以结点u为根的子树的结点数为cnt[u],则以结点v为根的子树的结点数为cnt[v]=N-cnt[u]。

回到式(*)中,则边(u,v)对式子的贡献为$w(u,v)*cnt[u]*cnt[v]$。

考虑通过DFS预处理cnt[]:选取某一个结点作为根结点,通过DFS预处理以结点u为根的子树的结点数cnt[u]。之后,遍历树上的边:连接结点v与其父结点的边,其对式子的贡献为$w(p[v],v)*cnt[v]*(N-cnt[v])$。

考虑到双向,答案为$ans=2(N-1)!\:*f(T)\mod M$。

参考程序如下:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. #define MAX_N 100005
  5.  
  6. const int64_t mod = 1e9 + ;
  7.  
  8. struct arrow
  9. {
  10. int to;
  11. int cost;
  12. arrow(int to = , int cost = ) : to(to), cost(cost) {}
  13. };
  14.  
  15. int64_t fact[MAX_N];
  16.  
  17. void init(void)
  18. {
  19. fact[] = ;
  20. for (int i = ; i < MAX_N; i++) fact[i] = fact[i - ] * i % mod;
  21. }
  22.  
  23. int n;
  24. vector<arrow> adj[MAX_N];
  25.  
  26. int64_t ans;
  27. int cnt[MAX_N];
  28.  
  29. void dfs_cnt(int u, int p)
  30. {
  31. cnt[u] = ;
  32. for (int i = ; i < adj[u].size(); i++) {
  33. int v = adj[u][i].to;
  34. if (v == p) continue;
  35. dfs_cnt(v, u);
  36. cnt[u] += cnt[v];
  37. }
  38. }
  39.  
  40. void dfs_calc(int u, int p)
  41. {
  42. for (int i = ; i < adj[u].size(); i++) {
  43. int v = adj[u][i].to;
  44. int w = adj[u][i].cost;
  45. if (v == p) continue;
  46. int64_t cur = 1ll * cnt[v] * (n - cnt[v]);
  47. ans += cur * w % mod;
  48. ans %= mod;
  49. dfs_calc(v, u);
  50. }
  51. }
  52.  
  53. int main(void)
  54. {
  55. ios::sync_with_stdio(false);
  56. init();
  57. while (cin >> n) {
  58. memset(cnt, , sizeof(cnt));
  59. for (int i = ; i < n; i++) {
  60. int u, v, w;
  61. cin >> u >> v >> w;
  62. adj[u].push_back(arrow(v, w));
  63. adj[v].push_back(arrow(u, w));
  64. }
  65. ans = ;
  66. dfs_cnt(, -);
  67. dfs_calc(, -);
  68. cout << 2ll * ans % mod * fact[n - ] % mod << endl;
  69. for (int i = ; i <= n; i++) adj[i].clear();
  70. }
  71. return ;
  72. }

HDU - 6446 Tree and Permutation的更多相关文章

  1. (1009) HDU 6446 Tree and Permutation(规律+树上各个点的距离和)

    题意: 给一棵N个点的树,对应于一个长为N的全排列,对于排列的每个相邻数字a和b,他们的贡献是对应树上顶点a和b的路径长,求所有排列的贡献和. 分析: 经过简单的分析可以得知,全部的贡献其实相当与(这 ...

  2. HDU 6446 Tree and Permutation(赛后补题)

    >>传送门<< 分析:这个题是结束之后和老师他们讨论出来的,很神奇:刚写的时候一直没有注意到这个是一个树这个条件:和老师讨论出来的思路是,任意两个结点出现的次数是(n-1)!, ...

  3. Tree and Permutation (HDU 6446) 题解

    // 昨天打了一场网络赛,表现特别不好,当然题目难度确实影响了发挥,但还是说明自己太菜了,以后还要多多刷题. 2018 CCPC 网络赛 I - Tree and Permutation 简单说明一下 ...

  4. 2018中国大学生程序设计竞赛 - 网络选拔赛 hdu Tree and Permutation 找规律+求任意两点的最短路

    Tree and Permutation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Oth ...

  5. HDU 5868 Different Circle Permutation(burnside 引理)

    HDU 5868 Different Circle Permutation(burnside 引理) 题目链接http://acm.hdu.edu.cn/showproblem.php?pid=586 ...

  6. hdu 5225 Tom and permutation(回溯)

    题目链接:hdu 5225 Tom and permutation #include <cstdio> #include <cstring> #include <algo ...

  7. hdu 5909 Tree Cutting [树形DP fwt]

    hdu 5909 Tree Cutting 题意:一颗无根树,每个点有权值,连通子树的权值为异或和,求异或和为[0,m)的方案数 \(f[i][j]\)表示子树i中经过i的连通子树异或和为j的方案数 ...

  8. HDU6446 Tree and Permutation(树上DP)

    传送门:点我 Tree and Permutation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (J ...

  9. 2018中国大学生程序设计竞赛 - 网络选拔赛 1009 - Tree and Permutation 【dfs+树上两点距离和】

    Tree and Permutation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Oth ...

随机推荐

  1. Tool:Adobe Photoshop

    ylbtech-Tool-Adobe:Adobe Photoshop 1.返回顶部 1. Adobe Photoshop,简称“PS”,是由Adobe Systems开发和发行的图像处理软件. Pho ...

  2. Ubuntu搭建Eclipse+JDK+SDK的Android (转载)

    转自:http://blog.csdn.net/ithomer/article/details/6960989 今晚重装Ubuntu系统,重新安装了一套eclipse+jdk+SDK的Android开 ...

  3. bootstrap的modal弹窗,在多层窗口关闭时只会关闭自窗口,不再关闭父窗口

    bootstrap多层modal弹窗时.当子窗口关闭时,所有父窗口一起关闭. 原因是bootstrap在窗口关闭事件委托时,委托给所有窗口. 如源码: this.$element.on('click. ...

  4. bzoj 1645: [Usaco2007 Open]City Horizon 城市地平线【线段树+hash】

    bzoj题面什么鬼啊-- 题目大意:有一个初始值均为0的数列,n次操作,每次将数列(ai,bi-1)这个区间中的数与ci取max,问n次后元素和 离散化,然后建立线段树,每次修改在区间上打max标记即 ...

  5. Web前端汇总

    http://www.cnblogs.com/bigboyLin/p/5272902.html HTML/CSS部分   1.什么是盒子模型? 在网页中,一个元素占有空间的大小由几个部分构成,其中包括 ...

  6. 设计基于HTML5的APP登录功能及安全调用接口的方式

    转自:http://blog.csdn.net/linlzk/article/details/45536065 最近发现群内大伙对用Hbuilder做的APP怎么做登录功能以及维护登录状态非常困惑,而 ...

  7. 安装Kali里的应用程序或软件包

    安装Kali里的应用程序或软件包 安装额外的软件是apt-get命令最基本的功能了,命令非常简单易懂.安装软件包的语法如下: apt-get install 软件包名 比如,安装图像编辑软件gimp, ...

  8. Kafka~消费的有效期

    消息的过期时间 我们在使用Kafka存储消息时,如果已经消费过了,再永久存储是一种资源的浪费,所有,kafka为我们提供了消息文件的过期策略,可以通过配置server.properies来实现# vi ...

  9. 【工具】前端Photoshop

    前端photoshop最常见问题: 字体单位换成像素:按下ctrl+k调出首选项,选择单位与标尺,在里面把文字单位由点改为像素就行了.不过要注意的是,点是很多软件里面文字的默认单位.像素是虚拟单位,如 ...

  10. Linux学习笔记之Linux命令

    1. blkid  查看当前系统中所有已挂载文件系统的类型