题意:

给一棵N个点的树,对应于一个长为N的全排列,对于排列的每个相邻数字a和b,他们的贡献是对应树上顶点a和b的路径长,求所有排列的贡献和

思路:

对每一条边,边左边有x个点,右边有y个点,x+y=n,权值为w,则答案为$\displaystyle \sum 2xyw(n-1)!=\sum 2x(n-x)w(n-1)!$

其中每条边的x可以通过一次dfs找子树节点个数

比赛的时候找不到怎么又存权值又存子树节点个数的方法,瞎瘠薄调最后卡着空间时间过的,后来看别人代码学到了新方法:

比赛代码:

842MS 14012K
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<vector>
#include<map>
#include<functional> #define fst first
#define sc second
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lc root<<1
#define rc root<<1|1
#define lowbit(x) ((x)&(-x)) using namespace std; typedef double db;
typedef long double ldb;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef pair<ll,ll> PLL; const db eps = 1e-;
const int mod = 1e9+;
const int maxn = 2e5+;
const int maxm = 2e6+;
const int inf = 0x3f3f3f3f;
const db pi = acos(-1.0);
vector<int>v[maxn];
ll w[maxn];
int f[maxn];
ll ans = ;
ll cnt[maxn];
ll dfs(int x, int fa){
ll tmp = ;
int sz = v[x].size();
if(sz==&&fa!=-)return f[x]=;
for(int i = ; i < sz; i++){
if(v[x][i]!=fa)tmp += dfs(v[x][i], x);
}
return f[x]=tmp;
}
void init(){
cnt[] = ;
for(int i = ; i < +; i++){
cnt[i] = cnt[i-]*i;
cnt[i]%=mod;
}
return;
}
inline int read(){
int num;
char ch;
while((ch=getchar())<'' || ch>'');
num=ch-'';
while((ch=getchar())>='' && ch<=''){
num=num*+ch-'';
}
return num;
}
struct Edge{
int u;
int v;
int w;
}edge[maxn];
int top = ;
void addedge(int u, int v, int w){
edge[top].u = u;
edge[top].v = v;
edge[top++].w = w;
} int main() {
int n;
init();
while(scanf("%d", &n)!=EOF){
top = ;
ans = ;
mem(f, );
for(int i = ; i <= n; i++){
v[i].clear();
}
for(int i = ; i <= n-; i++){
int x, y;
x=read();
y=read();
v[x].pb(y);
v[y].pb(x);
int c;
c = read();
addedge(x, y, c);
//mp[x][y] = mp[y][x] = c;
}
//ddfs(1, -1); dfs(, -);
f[] = ;
for(int i = ; i <= n-; i++){
int x = edge[i].u;
int y = edge[i].v;
int ww = edge[i].w;
//printf("%d %d %d %d\n", x, f[x], y, f[y]);
if(x==){
w[y] = ww;
continue;
}
else if(y==){
w[x] = ww;
continue;
}
if(f[x] < f[y]){
w[x] = ww;
continue;
}
else{
w[y] = ww;
continue;
}
} // for(int i = 1; i <= n; i++){
// printf("%d %d\n", i, w[i]);
// }
for(int i = ; i <= n; i++){
ll tmp = ;
tmp = *f[i];
tmp%=mod;
tmp *= (n-f[i]);
tmp%=mod;
tmp *= cnt[n-];
tmp %= mod;
tmp *= (ll)w[i];
ans += tmp;
ans %= mod;
}
printf("%I64d\n", ans);
} return ;
}

赛后代码:

499MS 18972K
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<vector>
#include<map>
#include<functional> #define fst first
#define sc second
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lc root<<1
#define rc root<<1|1
#define lowbit(x) ((x)&(-x)) using namespace std; typedef double db;
typedef long double ldb;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef pair<ll,ll> PLL; const db eps = 1e-;
const int mod = 1e9+;
const int maxn = 2e5+;
const int maxm = 2e6+;
const int inf = 0x3f3f3f3f;
const db pi = acos(-1.0); ll d[maxn];
struct Edge{
int u;
ll w;
};
vector<Edge>v[maxn];
ll w[maxn];
int f[maxn];
int dfs(int x, int fa){
int sz = v[x].size();
int ans = ;
for(int i = ; i < sz; i++){
if(v[x][i].u==fa)w[x]=v[x][i].w;
else ans+=dfs(v[x][i].u, x);
}
if(sz==&&fa!=-)return f[x] = ;
return f[x] = ans;
}
int main() {
int n;
d[] = ;
for(int i = ; i < + ; i++){
d[i] = d[i-] *i;
d[i] %= mod;
}
while(~scanf("%d", &n)){
for(int i = ; i <= n; i++)v[i].clear();
//mem(f, 0);
for(int i = ; i < n-; i++){
int x, y;
ll l;
scanf("%d %d %I64d", &x, &y, &l);
Edge t1, t2;
t1.u=y;t2.u=x;
t1.w=t2.w=l;
v[x].pb(t1);
v[y].pb(t2);
}
ll ans = ;
dfs(, -);
for(int i = ; i <= n; i++){
ll tmp = d[n-];
tmp %= mod;
tmp *= (ll)*f[i]*(n-f[i]);
tmp %= mod;
tmp *= w[i];
tmp %= mod;
ans += tmp;
ans %= mod;
}
printf("%I64d\n", ans);
}
return ;
}

HDU6446 Tree and Permutation(树、推公式)的更多相关文章

  1. hdu6446 Tree and Permutation 2018ccpc网络赛 思维+dfs

    题目传送门 题目描述:给出一颗树,每条边都有权值,然后列出一个n的全排列,对于所有的全排列,比如1 2 3 4这样一个排列,要算出1到2的树上距离加2到3的树上距离加3到4的树上距离,这个和就是一个排 ...

  2. HDU6446 Tree and Permutation(树上DP)

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

  3. 2020牛客寒假算法基础集训营2 J.求函数 (线段树 推公式 单点修改 区间查询)

    https://ac.nowcoder.com/acm/contest/3003/J 题解: #include<bits/stdc++.h> typedef long long ll; u ...

  4. hdu6446 Tree and Permutation

    没啥好说的,拆一下贡献就完事了.记dis(x,y)为树上x到y的最短路径,设长度为n的排列中有f(n)个里面x和y相邻(不考虑x和y的顺序),那么f(n)=(n-2)! (n-1) 2,显然这个f(n ...

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

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

  6. Tree and Permutation

    Tree and Permutation 给出一个1,2,3...N的排列,显然全部共有N!种排列,每种排列的数字代表树上的一个结点,设Pi是其中第i种排列的相邻数字表示的结点的距离之和,让我们求su ...

  7. Tree and Permutation (HDU 6446) 题解

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

  8. HDU 4873 ZCC Loves Intersection(JAVA、大数、推公式)

    在一个D维空间,只有整点,点的每个维度的值是0~n-1 .现每秒生成D条线段,第i条线段与第i维度的轴平行.问D条线段的相交期望. 生成线段[a1,a2]的方法(假设该线段为第i条,即与第i维度的轴平 ...

  9. HDU 4870 Rating(概率、期望、推公式) && ZOJ 3415 Zhou Yu

    其实zoj 3415不是应该叫Yu Zhou吗...碰到ZOJ 3415之后用了第二个参考网址的方法去求通项,然后这次碰到4870不会搞.参考了chanme的,然后重新把周瑜跟排名都反复推导(不是推倒 ...

随机推荐

  1. SQL练习题(一)

    目录 题目一:交换性别(简单) 实现思路 提交代码 题目二:连续出现的数字(中等) 实现思路 方式一 方式二 提交代码 方式一 方式二 题目三:换座位(中等) 实现思路 方式一 方式二 提交代码 方式 ...

  2. 【一起学源码-微服务】Feign 源码三:Feign结合Ribbon实现负载均衡的原理分析

    前言 前情回顾 上一讲我们已经知道了Feign的工作原理其实是在项目启动的时候,通过JDK动态代理为每个FeignClinent生成一个动态代理. 动态代理的数据结构是:ReflectiveFeign ...

  3. 小白学 Python 爬虫(38):爬虫框架 Scrapy 入门基础(六) Item Pipeline

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  4. echarts更改轴线颜色

    xAxis : [ { type : 'category', data : ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月 ...

  5. 谈谈Java的Collection接口

    目录 谈谈Collection 前言 Collection 方法 1.boolean add(E) 2.void clear() 3.boolean contains(Object o) 4.bool ...

  6. Python中函数参数 *args 和 **kwargs

    普通参数,即在调用函数时必须按照准确的顺序来进行参数传递. 默认参数,即参数含有默认值,在调用函数时可以进行参数传递,若没有进行参数传递则使用默认值,要注意,默认参数必须在普通参数的右侧(否则解释器无 ...

  7. numpy基本知识

    """np.arrayobject 数组或嵌套的数列dtype 数组元素的数据类型,可选copy 对象是否需要复制,可选order 创建数组的样式,C为行方向,F为列方向 ...

  8. Djaingo 随机生成验证码(PIL)

    基础: https://www.cnblogs.com/wupeiqi/articles/5812291.html 实例: https://www.cnblogs.com/6324TV/p/88112 ...

  9. 头条一面竟然问我Maven?

    maven package和maven install 有什么区别? 你常用的maven命令有哪些? <dependencyManagement> 是干什么的? 还有用过其它构建工具吗? ...

  10. Oracle GoldenGate for DB2

    --Enable logdb2 update db cfg using LOGARCHMETH1 DISK:/home/db2inst1/arclogs--Rebootdb2 terminatedb2 ...