Codeforces
来源:互联网 发布:淘宝店铺怎样加粉丝 编辑:程序博客网 时间:2024/06/05 16:35
New Year Santa Network
题目链接
分类:树形dp、思维、数学
1.题意概述
- 给你由n个节点构成的树,有(n-1)条边,随机选取其中三个节点a、b、c,定义
dist=dis(a,b)+dis(b,c)+dis(c,a) ,现在有q次操作,每次选取某条边,使得它的边权由原先的wi 变成li ,问你每次操作以后的期望E(dist) 是多少?
2.解题思路
- 根据期望性质
E[dis(a,b)+dis(b,c)+dis(c,a)]=E[dis(a,b)]+E[dis(b,c)]+E[dis(c,a)] - 方法一:按边考虑,n个点中任意取3个点的取法是
C3n 种,我们考虑每条边出现的概率。如果我们选定边ab ,那么第三个点c 就在剩下的(n−2) 个点中取,也就是边ab 会出现(n−2) 次,假设这条边下面的儿子个数为son[x] ,而经过这条边的种类数son[x]⋅(n−son[x]) ,所以最终概率为pab=son[x](n−son[x])(n−2)C3n ,而总的期望就是E(dist)=∑E[dis(i,j)]=pij⋅wij !而统计儿子个数我们可以通过树形dp跑一遍dfs就可以求得,而每条边的权值的变动,只会影响wij ,根据期望性质,我们可以先求得边尚未改变的期望,然后减去(lij−wij)⋅pij 就是结果! - 方法二:按点考虑,画图容易发现,树中任意选三点构成合法路线,某条边一定会经过两次,那么我们对于这条边两侧的点考虑,假设左侧有
a 个点,右侧有b 个点,那么这三个点的选法有C2a⋅C1b+C1a⋅C2b 种,结果就是2(C2a⋅C1b+C1a⋅C2b)C3n ,下面做法和方法一类似。
- 方法一:按边考虑,n个点中任意取3个点的取法是
3.AC代码
#include <bits/stdc++.h>#define INF 0x3f3f3f3f#define maxn 100010#define lson root << 1#define rson root << 1 | 1#define lent (t[root].r - t[root].l + 1)#define lenl (t[lson].r - t[lson].l + 1)#define lenr (t[rson].r - t[rson].l + 1)#define N 1111#define eps 1e-6#define pi acos(-1.0)#define e exp(1.0)#define Close() ios::sync_with_stdio(0),cin.tie(0)using namespace std;const int mod = 1e9 + 7;typedef long long ll;typedef unsigned long long ull;struct node{ int to, id; node(int a, int b) { to = a; id = b; }};vector<node> g[maxn];double p[maxn];int son[maxn], w[maxn];void dfs(int u, int fa, int pid, const int &n){ son[u] = 1; int sz = g[u].size(); for (int i = 0; i < sz; i++) { int v = g[u][i].to; int id = g[u][i].id; if (v != fa) { dfs(v, u, id, n); son[u] += son[v]; } } p[pid] = 6.0 * son[u] * (n - son[u]) / n / (n - 1);}int main(){#ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); long _begin_time = clock();#endif int n, m; scanf("%d", &n); for (int i = 1; i < n; i++) { int a, b; scanf("%d%d%d", &a, &b, &w[i]); g[a].push_back(node(b, i)); g[b].push_back(node(a, i)); } dfs(1, -1, 0, n); double ans = 0; for (int i = 1; i < n; i++) ans += w[i] * p[i]; scanf("%d", &m); while (m--) { int a, b; scanf("%d%d", &a, &b); int delta = w[a] - b; ans -= delta * p[a]; printf("%.12f\n", ans); w[a] -= delta; }#ifndef ONLINE_JUDGE long _end_time = clock(); printf("time = %ld ms.", _end_time - _begin_time);#endif return 0;}
阅读全文
0 0
- codeforces~~~
- Codeforces
- codeforces
- Codeforces
- codeforces
- codeforces
- Codeforces
- Codeforces
- CodeForces
- CodeForces
- CodeForces
- CodeForces
- CodeForces
- Codeforces
- Codeforces
- Codeforces
- Codeforces
- Codeforces
- 线程安全和可重入函数
- Spring Aop源码学习--Aop代理工厂AopProxyFactory
- JavaScript与用户互动
- Intellij 打开就闪退或关闭
- react native 调用原生UI组件
- Codeforces
- IOC的理解
- dagger2理解分享_实现解耦
- python3 [爬虫入门实战]爬虫之mongoDB数据库的安装配置与可视化
- stamen的程序员之路
- 计算几何之旋转卡壳算法
- can not load com.mysql.jdbc.Driver
- Google Hacking!
- android按home键再启动程序camera黑屏&屏蔽home键