Title Address: Http://codeforces.com/contest/500/problem/D
The problem is to find out the number of times each edge appears, and then divide by the total number of times, so that expectations are found. First use the tree-shaped DP to find out the total number of points at the left and right ends of each edge, and then use the combination of mathematical formula can be pushed out.
The code is as follows:
#include <iostream> #include <string.h> #include <math.h> #include <queue> #include < algorithm> #include <stdlib.h> #include <map> #include <set> #include <stdio.h>using namespace std; #define LL __int64int vis[110000];int head[110000], CNT, n; LL fx[110000], fy[110000], dp[110000], w[110000];struct node {int u, V, W, id, next;} edge[210000];void Add (int u, int v, LL w, int id) {edge[cnt].v=v; Edge[cnt].w=w; Edge[cnt].id=id; Edge[cnt].next=head[u]; head[u]=cnt++;} void Dfs (int u) {dp[u]=1; Vis[u]=1; for (int i=head[u]; i!=-1; i=edge[i].next) {int v=edge[i].v; if (Vis[v]) continue; DFS (v); printf ("---%.2f\n", ans); FX[EDGE[I].ID]=DP[V]; FY[EDGE[I].ID]=N-DP[V]; DP[U]+=DP[V]; }}void init () {memset (head,-1,sizeof (head)); cnt=0; memset (vis,0,sizeof (VIS));}int Main () {int I, J, u, V, m, K, T; scanf ("%d", &n); Init (); for (i=0; i<n-1; i++) {scanf ("%d%d%i64d", &u,&v,&w[i]); Add (u,v,w[i],i); Add (v,u,w[i],i); } dfs (1); Double ans=0; for (i=0;i<n;i++) {ans+=fx[i]* (fx[i]-1) *fy[i]*w[i]+fx[i]* (fy[i]-1) *fy[i]*w[i]; } scanf ("%d", &m); while (m--) {scanf ("%d%d", &k,&t); k--; printf ("--%.3f\n", ans); ans-=fx[k]* (fx[k]-1) *fy[k]* (w[k]-t) +fx[k]*fy[k]* (fy[k]-1) * (W[K]-T); printf ("---%.3f\n", ans); w[k]=t; printf ("%.9f\n", ans/n/(n-1)/(n-2) *6); } return 0;}
Codeforces 500d-new year Santa Network (tree-shaped dp+ combinatorial mathematics)