codeforces Goodbye 2014 D题(树上统计,DFS)

2015-01-01 01:35:27

思路:这道题是有母题的....hdu 2376

  比赛时花了一个多小时想....后来sb地搞成了树形DP,死活不过(逃QAQ.....

  其实就是计算每条边的对结果的贡献,在n个点里选3个点的总情况数是total = n * (n - 1) * (n - 2) / 6

  选某条边作为要建的边的情况数如何计算呢?设这条边的某一侧的子树大小为sz,那么应该是 sz * (n - sz) * (n - 2),先在两边任选一个点,然后在剩余的(n-2)个点中再任选一个点。

  某条边的贡献:w[i] * sz * (n - sz) * (n - 2) / total

  至于删边同理,处理所删掉部分的负贡献。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 int a,b,n,q,sz[100010];
 5 ll dtr[100010];
 6 vector<int> g[100010];
 7 struct edge{ int u,v,c;}e[200010];
 8 void Dfs(int p,int fa){
 9     sz[p] = 1;
10     for(int i = 0; i < g[p].size(); ++i) if(g[p][i] != fa){
11         int v = g[p][i];
12         Dfs(v,p),sz[p] += sz[v];
13     }
14 }
15 int main(){
16     scanf("%d",&n);
17     for(int i = 1; i < n; ++i){
18         scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].c);
19         g[e[i].u].push_back(e[i].v);
20         g[e[i].v].push_back(e[i].u);
21     }
22     Dfs(1,0);
23     double ans = 0.0;
24     ll total = (ll)n * (n - 1) * (n - 2) / 6LL;
25     for(int i = 1; i < n; ++i){
26         ll siz = min(sz[e[i].u],sz[e[i].v]);
27         dtr[i] = siz * (n - siz) * (n - 2);
28         ans += (double)dtr[i] * e[i].c / total;
29     }    
30     for(scanf("%d",&q); q; --q){
31         scanf("%d%d",&a,&b);
32         ans -= (double)dtr[a] * (e[a].c - b) / total,e[a].c = b;
33         printf("%.10f\n",ans);
34     }
35     return 0;
36 }

 

posted @ 2015-01-01 01:39  Naturain  阅读(127)  评论(0编辑  收藏  举报