codeforces goodbye2014 D树上取三点,求三边距离和期望(树上dfs)

算出每个边被选中概率,然后每条边权×概率,和即为答案。

一共有C(n,3)种选法,每条边下边有down[x]个,上面有n-down[x]个,选取该边方法有down[x]*(n-down[x])*(n-2) thinking==

然后初以总选法就是概率。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 int now=0,head[200005],next[200005],point[200005];
 6 int down[100005],l[100005],r[100005],w[100005],num[100005];
 7 double g[100005];
 8 void add(int u,int v,int w)
 9 {
10   next[++now]=head[u];
11   head[u]=now;
12   point[now]=v;
13 }
14 void dfs(int pre,int u)
15 {
16   down[u]=1;
17   for (int i=head[u];i;i=next[i])
18   {
19     int v=point[i];
20     if (v==pre) continue;
21     dfs(u,v);
22     down[u]+=down[v];
23   }
24 }
25 int main()
26 {
27   int t1,t2,n,i,q,tmp;
28   double sum,ans;
29   scanf("%d",&n);
30   memset(head,0,sizeof(head));
31   for (i=1;i<n;i++)
32   {
33     scanf("%d%d%d",&l[i],&r[i],&w[i]);
34     add(l[i],r[i],w[i]);
35     add(r[i],l[i],w[i]);
36   }
37   sum=1.0*n*(n-1)*(n-2)/6.0;
38   memset(down,0,sizeof(down));
39   dfs(0,1);
40   memset(num,0,sizeof(num));
41   for (i=1;i<=n;i++)
42     num[i]=down[i]*(n-down[i])*(n-2);
43   ans=0.0;
44   for (i=1;i<n;i++)
45   {
46     tmp=min(down[l[i]],down[r[i]]);//thinking==
47     g[i]=1.0*tmp*(n-tmp)*(n-2);
48     ans=ans+w[i]*g[i]/sum;
49   }
50   scanf("%d",&q);
51   while (q--)
52   {
53     scanf("%d%d",&t1,&t2);
54     ans-=1.0*(w[t1]-t2)*g[t1]/sum;
55     w[t1]=t2;
56     printf("%lf\n",ans);
57   }
58   return 0;
59 }

题目链接:http://codeforces.com/contest/500/problem/D

posted on 2014-12-31 16:30  xiao_xin  阅读(235)  评论(0编辑  收藏  举报

导航