hdu6446 网络赛 Tree and Permutation(树形dp求任意两点距离之和)题解
题意:有一棵n个点的树,点之间用无向边相连。现把这棵树对应一个序列,这个序列任意两点的距离为这两点在树上的距离,显然,这样的序列有n!个,加入这是第i个序列,那么这个序列所提供的贡献值为:第一个点到其他所有点距离之和。求所有序列贡献值之和。
思路:假如第一个点是k,那么后面n-1个点共有(n - 1)!种排列,也就是说,第一个点是k那么这样的序列的贡献值为(n - 1)!*(k到其他点距离之和),显然最后答案应该是所有点之间的距离和的两倍 *(n - 1)!。问题转化为了求一棵树上所有点之间的距离,怎么求呢?
假设有一条边E,那么如果要经过E这条边,必然是两个端点在E的两边,假设左边有M点,右边有(n - M)个点,那么一共经过E次数2 *(n - M)* M,所以E的贡献长度为2 *(n - M)* M * E的权值,最后把每条边的贡献长度加在一起就是所有点之间的距离。至于求E两边点数,只要算每个点的子节点数(包括自己)就行了。
MOD值赋错了wa了一下午...写了两个版本...
标解:

参考:HDU2376Average distance(树形dp|树上任意两点距离和的平均值)
代码:
/*DP*/
#include<map>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = + ;
const int seed = ;
const int MOD = + ;
const int INF = 0x3f3f3f3f;
struct Edge{
ll w;
int u, v, next;
}edge[maxn << ];
ll fac[maxn], dp[maxn], num[maxn], ans;
int head[maxn], tot, n;
void init(){
fac[] = ;
for(int i = ; i < maxn; i++){
fac[i] = (fac[i - ] * i) % MOD;
}
}
void addEdge(ll u, ll v, ll w){
edge[tot].u = u;
edge[tot].v = v;
edge[tot].w = w;
edge[tot].next = head[u];
head[u] = tot++;
}
void dfs(int u, int pre){
num[u] = ;
for(int i = head[u]; i != -; i = edge[i].next){
int v = edge[i].v;
ll w = edge[i].w;
if(v == pre) continue;
dfs(v, u);
num[u] += num[v];
dp[u] = (dp[u] + dp[v] + w * num[v] % MOD * (n - num[v]) % MOD) % MOD;
}
}
int main(){
init();
while(~scanf("%d", &n)){
memset(head, -, sizeof(head));
memset(dp, , sizeof(dp));
tot = ;
for(int i = ; i < n - ; i++){
ll u, v, w;
scanf("%lld%lld%lld", &u, &v, &w);
addEdge(u, v, w);
addEdge(v, u, w);
}
ans = ;
dfs(, -);
ans = dp[] * 2LL % MOD * fac[n - ] % MOD;
printf("%lld\n", ans);
}
return ;
}
/*直接代公式*/
#include<map>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = + ;
const int seed = ;
const int MOD = + ;
const int INF = 0x3f3f3f3f;
struct Edge{
ll w;
int u, v, next;
}edge[maxn << ];
ll fac[maxn], ans;
int head[maxn], family[maxn], tot, n;
void init(){
fac[] = ;
for(int i = ; i < maxn; i++){
fac[i] = (fac[i - ] * i) % MOD;
}
}
void addEdge(ll u, ll v, ll w){
edge[tot].u = u;
edge[tot].v = v;
edge[tot].w = w;
edge[tot].next = head[u];
head[u] = tot++;
}
int dfs(int u, int pre){
family[u] = ;
for(int i = head[u]; i != -; i = edge[i].next){
if(edge[i].v == pre) continue;
family[u] += dfs(edge[i].v, u);
}
return family[u];
}
int main(){
init();
while(~scanf("%d", &n)){
memset(head, -, sizeof(head));
tot = ;
for(int i = ; i < n - ; i++){
ll u, v, w;
scanf("%lld%lld%lld", &u, &v, &w);
addEdge(u, v, w);
addEdge(v, u, w);
}
ans = ;
dfs(, -);
for(int i = ; i < tot; i += ){
ll temp;
temp = (2LL * family[edge[i].v] * (n - family[edge[i].v])) % MOD;
temp = (temp * edge[i].w) % MOD;
temp = (temp * fac[n - ]) % MOD;
ans += temp;
ans %= MOD;
}
printf("%lld\n", ans);
}
return ;
}
hdu6446 网络赛 Tree and Permutation(树形dp求任意两点距离之和)题解的更多相关文章
- 2018中国大学生程序设计竞赛 - 网络选拔赛 hdu Tree and Permutation 找规律+求任意两点的最短路
Tree and Permutation Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Oth ...
- HDU 2376 树形dp|树上任意两点距离和的平均值
原题:http://acm.hdu.edu.cn/showproblem.php?pid=2376 经典问题,求的是树上任意两点和的平均值. 这里我们不能枚举点,这样n^2的复杂度.我们可以枚举每一条 ...
- HDU2376Average distance(树形dp|树上任意两点距离和的平均值)
思路: 引:如果暴力枚举两点再求距离是显然会超时的.转换一下思路,我们可以对每条边,求所有可能的路径经过此边的次数:设这条边两端的点数分别为A和B,那 么这条边被经过的次数就是A*B,它对总的距离和的 ...
- HDU 5723 Abandoned country(kruskal+dp树上任意两点距离和)
Problem DescriptionAn abandoned country has n(n≤100000) villages which are numbered from 1 to n. Sin ...
- 吉首大学2019年程序设计竞赛(重现赛)-J(树形DP)
题目链接:https://ac.nowcoder.com/acm/contest/992/J 题意:题意很清晰,就是求任意两点距离的和,结果对1e9+7取模. 思路:裸的树形DP题,一条边的贡献值=这 ...
- Codeforces 791D Bear and Tree Jump(树形DP)
题目链接 Bear and Tree Jumps 考虑树形DP.$c(i, j)$表示$i$最少加上多少后能被$j$整除. 在这里我们要算出所有$c(i, k)$的和. 其中$i$代表每个点对的距离, ...
- [HDU 5293]Tree chain problem(树形dp+树链剖分)
[HDU 5293]Tree chain problem(树形dp+树链剖分) 题面 在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大. 分析 考虑树形dp,dp[x]表示以x为子树 ...
- HDU 4514 - 湫湫系列故事——设计风景线 - [并查集判无向图环][树形DP求树的直径]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514 Time Limit: 6000/3000 MS (Java/Others) Memory Li ...
- 浅谈关于树形dp求树的直径问题
在一个有n个节点,n-1条无向边的无向图中,求图中最远两个节点的距离,那么将这个图看做一棵无根树,要求的即是树的直径. 求树的直径主要有两种方法:树形dp和两次bfs/dfs,因为我太菜了不会写后者这 ...
随机推荐
- mysql transaction 事务
1.事务简介 一个"最小的"不可再分的"工作单元". 一个事务通常对应了一个完整的业务.如:银行的转账功能,a转账给b,a扣钱,b加钱. 一个事务包含一条或多条 ...
- java注解使用
1:定义注解 package chapter20.one; import java.lang.annotation.ElementType; import java.lang.annotation.R ...
- Centos 设置zookeeper开机自启动
把zookeeper做成服务 1.进入到/etc/rc.d/init.d目录下,新建一个zookeeper脚本 [root@zookeeper ~]# cd /etc/rc.d/init.d/ [ro ...
- X-Forwarded-For 负载均衡 7 层 HTTP 模式获取来访客户端真实 IP 的方法(IIS/Apache/Nginx/Tomcat)
https://help.aliyun.com/knowledge_detail/13051859.html?pos=1 1.IIS 6 配置方案2.IIS 7 配置方案3.Apache 配置方案4. ...
- jmeter 线程组之间的参数传递(加密接口测试三)
场景测试中,一次登录后做多个接口的操作,然后登录后的uid需要关联传递给其他接口发送请求的时候使用. 1.在登录接口响应信息中提取uid字段值 1>login请求 -->添加 --> ...
- Lintcode: Insert Node in a Binary Search Tree
Given a binary search tree and a new tree node, insert the node into the tree. You should keep the t ...
- JS中“==”和“===”的原理和区别
1.为什么讨论这个问题? - 有个说法,尽量不用==,而使用===,是这样吗? 2.分析问题,原理是什么? 下面说说ECMAScript 5 language specification里的说明: 1 ...
- SV搭建验证环境
1)首先定义纯虚类Sv_object,主要实现下边两个function: 定义local static 变量nextobjectID; 虚方法 virtual function void copy(S ...
- n的二进制中有几个1
实例十七:n的二进制中有几个1 方法:result=n & (n-1) n&(n-1)的目的使最低位的1不断翻转. 比如:n=108,其二进制表示为0110 1100,则n& ...
- Trove系列(四)—Trove的快照功能介绍
Trove 快照用于支持DbaaS 备份,复制等功能.在Trove API (guest_agent)上将支持本功能.本功能将能够支持快照,从而用来进行副本设置,主数据库克隆和备份,以及数据恢复.目前 ...