题意:

给一棵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. [Windows10]记一次修复注册表相关血案:该文件没有与之关联的应用来执行该操作。请安装应用,若已经安装应用,请在“默认应用设置”页面中创建关联。

    今天闲得蛋疼清理了一下右键菜单,于是在之后某时刻使用Everything的“双击路径列打开目录”功能时发现异常: [Window Title] Everything.exe [Content] 该文件 ...

  2. linux条件变量使用和与信号量的区别

    近来在项目中用到条件变量和信号量做同步时,这一块一直都有了解,但也一直没有总结,这次总结一下,给大家提供点参考,也给自己留点纪念. 首先,关于信号量和条件变量的概念可以自行查看APUE,我这直接把AP ...

  3. openjudge 7622 求排列的逆序数(归并)

    7622:求排列的逆序数 总时间限制:  1000ms   内存限制:  65536kB 描述 在Internet上的搜索引擎经常需要对信息进行比较,比如可以通过某个人对一些事物的排名来估计他(或她) ...

  4. 比特币学习笔记(二)---在windows下调试比特币源码

    根据我一贯的学习经验,学习开源代码的话,单单看是不够的,必须一边看一边调试才能尽快理解,所以我们要想法搭建windows下bitcoin源码的调试环境. 紧接着昨天的进度,想要调试linux下的比特币 ...

  5. js删除数组的某个元素

    最近在刷算法题,我是用js语言去写的,其中一题需要删除数组的某个元素,查了一下资料,总结一下 使用splice()方法 array.splice(start[, deleteCount[, item1 ...

  6. 开源项目SMSS开源项目(三)——protobuf协议设计

    本文的第一部分将介绍protobuf使用基础以及如何利用protobuf设计通信协议.第二部分会给出smss项目的协议设计规范和源码讲解. 一.Protobuf使用基础 什么是protobuf pro ...

  7. 三、JVM之方法区

    一.什么式方法区 方法区,也称非堆(Non-Heap),又是一个被线程共享的内存区域.其中主要存储加载的类字节码.class/method/field等元数据对象.static-final常量.sta ...

  8. 初探ASP.NET Core 3.x (1) - 关于ASP.NET Core

    I 什么是ASP.NET Core ASP.NET is an open source web framework, created by Microsoft, for building modern ...

  9. DP-直线分割递推

    在 DP  里有一类是直线分割平面的问题 , 也是属于递推 类的 . 一 . 直线分割平面的问题 先考虑第一个小问题 : n 条直线最多可以将平面分割成几部分 ? 想想 最优的分割方法是怎样的呢 ? ...

  10. .net生成荣誉证书

    参考:https://blog.csdn.net/ljk126wy/article/details/84299373 采用生成pdf 方式  效果如下: 用adobe acrobat 制作一个模板  ...