题意:

给一棵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. mongodb 更新嵌套数组的值

    概要 本文主要讲述在 mongodb 中,怎么更新嵌套数组的值. 使用$更新数组 基本语法  { "<array>.$" : value } 可以用于:update, ...

  2. 正则表达式grep命令

    grep命令 作用:文本搜索工具,根据用户指定的“模式”对目标文本逐行进行匹配检查:打印匹配到的行. 模式::由正则表达式字符及文本字符所编写的过滤条件 语法:grep [OPTIONS] PATTE ...

  3. 图解kubernetes调度器ScheduleAlgorithm核心实现学习框架设计

    ScheduleAlgorithm是一个接口负责为pod选择一个合适的node节点,本节主要解析如何实现一个可扩展.可配置的通用算法框架来实现通用调度,如何进行算法的统一注册和构建,如何进行metad ...

  4. linux入门系列7--管道符、重定向、环境变量

    前面文章我们学习了linux基础命令,如果将不同命令组合使用则可以成倍提高工作效率.本文将学习重定向.管道符.通配符.转义符.以及重要的环境变量相关知识,为后面的shell编程打下基础. 一.IO重定 ...

  5. 大白话原型模式(Prototype Pattern)

    意图 原型模式是创建型设计模式,可以复制已存在的对象而无需依赖它的类. 问题 假如现在有一个对象,我们想完全复制一份新的,我们该如何做? 创建同一个类的新对象 遍历所有已存在对象的值,然后将他们的值复 ...

  6. 【C_Language】---C文件学习

    ---恢复内容开始--- 又看了一遍文件的知识点了,断断续续已经看了2-3遍,也就这次花了点时间做了一下总结,以后我想都不会再去翻书了,哈哈. 1. 基于缓冲区的文件操作2. 打开关闭文件3. 单个字 ...

  7. 主席树 - 查询某区间第 K 大

    You are working for Macrohard company in data structures department. After failing your previous tas ...

  8. java main 方法

    public static void main(String[] args) { BigDecimal b1 = new BigDecimal(0.01000000); BigDecimal b2 = ...

  9. windows环境下使用python3.x自带的CGI服务器测试cgi脚本(转)

    1.在桌面上新建一个文件夹作为服务器目录文件夹(文件夹名称自定义,文件夹位置自定义),在www文件下再建一个文件夹,文件夹名为“cgi-bin”,须是这个文件名,其他试过不行(原因暂时未知)

  10. Nginx作为负载均衡服务介绍

    ​ GSLB ​ SLB ​ 四层负载均衡 ​ 七层负载均衡 ​ 四层负载均衡 四层负载均衡工作在OSI模型的传输层,由于在传输层,只有TCP/UDP协议,这两种协议中除了包含源IP.目标IP以外,还 ...