Question Link
Question:
A weighted undirected graph with n points n-1 or n edges is provided. Start from each point and never go through another point. What is the mathematical expectation of the path length?
N <= 100000. In the figure, there is at most one ring, and the length of the Ring cannot exceed 20.
Question:
First, consider a tree:
First, take a node as the root node (for example, point 1) and create a tree chart.
The expected length of the Child tree where I goes is f [I], and the child nodes of I are S1, S2 ...... SK.
If d [I] = Σ (F [SJ] + edge (I, SJ) is set, F [I] = d [I]/K.
If P [I] is set to I as the expected length of the start point, P [1] = f [1] and Du [I] is the degree of node I.
Run the DFS again. If Y is a subnode of X, p [x] has been calculated.
The expected contribution of node y to X is other, other = (P [x] * Du [x]-edge (x, y)-f [x]). /(Du [x]-1) + edge (x, y)
P [y] = (Other + d [y])/du [y]
In this way, the P values of all vertices can be calculated through two DFS operations.
However, this question may be a base ring tree.
First, you can find this ring through DFS. If you remove this ring, it is the forest composed of some sub-trees.
First, use the aforementioned tree-like motion gauge method to process these sub-trees and find D and F.
Then we noticed that there were few points on the ring, so we calculated each point on the ring as the starting point.
For point X on the ring, set calc_pre (X) to the expected length from X to the left side of the ring, calc_nxt (X) the expected length obtained from the right side of the X-ring.
If SX is X.
Then P [x] = (Σ (F [SX] + edge (x, SX) + calc_pre (x) + calc_nxt (x)/du (X ).
Among them, calc_pre and calc_nxt can be calculated based on the complexity of O (number of points on the ring.
So we can calculate the p of all points in DFS again.
Ans = (Σ p [I])/n
/************************************************************** Problem: 2878 User: zrts Language: C++ Result: Accepted Time:588 ms Memory:10748 kb****************************************************************/ #include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<vector>//by zrt//problem:using namespace std;typedef long long LL;const int inf(0x3f3f3f3f);const double eps(1e-9);bool oncircle[100005];int du[100005];int fa[100005];int H[100005],X[200005],P[200005],tot;double E[200005];inline void add(int x,int y,int z){//add an edge P[++tot]=y;X[tot]=H[x];H[x]=tot;E[tot]=z;}int n,m;double F[100005];//for son Edouble D[100005];// F * |son|double p[100005];// ansint num[100005];// |son|int pre[100005];double wpre[100005];bool type;void treedp1(int x){//Dp the tree first for(int i=H[x];i;i=X[i]){ if(P[i]==fa[x]||oncircle[P[i]]) continue; fa[P[i]]=x; treedp1(P[i]); D[x]+=F[P[i]]+E[i];num[x]++; } if(num[x]) F[x]=D[x]/num[x]; else F[x]=0;}void treedp2(int x,double edge){//Dp the tree second | calc the P double other; if(!fa[fa[x]]) { if(!type){ if(num[fa[x]]>1) other=(p[fa[x]]*(num[fa[x]]+0)-edge-F[x])/(num[fa[x]]-1)+edge; else other=edge; }else{ other=(p[fa[x]]*(num[fa[x]]+2)-edge-F[x])/(num[fa[x]]+1)+edge; } } else other=(p[fa[x]]*(num[fa[x]]+1)-edge-F[x])/num[fa[x]]+edge; p[x]=(other+D[x])/(num[x]+1); for(int i=H[x];i;i=X[i]){ if(P[i]==fa[x]||oncircle[P[i]]) continue; treedp2(P[i],E[i]); }}vector<int> circle;bool ok;int nxt[100005];double wnxt[100005];void findcircle(int x,int fa){ for(int i=H[x];i;i=X[i]){ if(P[i]==fa) continue; if(pre[P[i]]){ ok=1; int k=x; pre[P[i]]=x; wpre[P[i]]=E[i]; do{ oncircle[k]=1; circle.push_back(k); k=pre[k]; }while(k!=P[i]); oncircle[k]=1; circle.push_back(k); }else{ pre[P[i]]=x;wpre[P[i]]=E[i]; findcircle(P[i],x); if(ok) return; } }}double calc_nxt(int now,int end){ double ret=wnxt[now]; now=nxt[now]; int extra=0; if(nxt[now]!=end) ret+=calc_nxt(now,end)/(du[now]-1); else extra=-1; for(int i=H[now];i;i=X[i]){ if(oncircle[P[i]]) continue; ret+=(E[i]+F[P[i]])/(du[now]-1+extra); } return ret;}double calc_pre(int now,int end){ double ret=wpre[now]; now=pre[now]; int extra=0; if(pre[now]!=end) ret+=calc_pre(now,end)/(du[now]-1); else extra=-1; for(int i=H[now];i;i=X[i]){ if(oncircle[P[i]]) continue; ret+=(E[i]+F[P[i]])/(du[now]-1+extra); } return ret;}int main(){// the main function #ifdef LOCAL freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif scanf("%d%d",&n,&m); for(int i=0,x,y,z;i<m;i++){ scanf("%d%d%d",&x,&y,&z); du[x]++; du[y]++; add(x,y,z); add(y,x,z); } if(m==n-1){ treedp1(1); p[1]=F[1]; for(int i=H[1];i;i=X[i]){ treedp2(P[i],E[i]); } double ans=0; for(int i=1;i<=n;i++){ ans+=p[i]; } printf("%.5f\n",ans/n); }else{ type=1; pre[1]=-1; findcircle(1,-1); for(int now=0;now<circle.size();now++){ nxt[pre[circle[now]]]=circle[now]; wnxt[pre[circle[now]]]=wpre[circle[now]]; } for(int now=0;now<circle.size();now++){ for(int i=H[circle[now]];i;i=X[i]){ if(oncircle[P[i]]) continue; treedp1(P[i]); p[circle[now]]+=(F[P[i]]+E[i])/du[circle[now]]; num[circle[now]]++; } } for(int now=0;now<circle.size();now++){ p[circle[now]]+=(calc_pre(circle[now],circle[now])+calc_nxt(circle[now],circle[now]))/du[circle[now]]; } for(int now=0;now<circle.size();now++){ for(int i=H[circle[now]];i;i=X[i]){ if(oncircle[P[i]]) continue; fa[P[i]]=circle[now]; treedp2(P[i],E[i]); } } double ans=0; for(int i=1;i<=n;i++){ ans+=p[i]; } printf("%.5f\n",ans/n); } return 0;}
Bzoj 2878: [noi2012] lost amusement park