Codeforces 629 E. Famil Door and Roads
题目链接:http://codeforces.com/problemset/problem/629/E
询问这个简单环的期望。考虑将这个环拆成两部分。
令${deep[x]>=deep[y]}$,${size[x]}$表示以$x$为根的子树大小,${sdown[x]}$示以$x$为根的子树的所有节点到$x$的距离和,${sall[x]}$所有点到$x$的距离和。${ne}$表示从${y-->x}$路径上${y}$的儿子。
1.${dis(x,y)}$这是一个环肯定要经过的,算入答案。
2.分情况考虑:
若是${lca(x,y)!=y}$,会产生${\frac{sdown[x]}{size[x]}+\frac{sdown[y]}{size[y]}}$的贡献。
若是${lca(x,y)=y}$,会产生${\frac{sdown[x]}{size[x]}+\frac{sdall[y]-sdown[ne]-size[ne]}{n-size[ne]}}$的贡献。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 #include<cstdlib> 6 #include<cmath> 7 #include<cstring> 8 using namespace std; 9 #define maxn 200010 10 #define llg long long 11 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); 12 llg n,m,T; 13 llg sall[maxn],sdown[maxn],deep[maxn],f[maxn][21],size[maxn]; 14 vector<llg>a[maxn]; 15 16 inline llg getint() 17 { 18 llg w=0,q=0; char c=getchar(); 19 while((c<'0' || c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); 20 while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w; 21 } 22 23 void dfs1(llg x,llg fa) 24 { 25 llg w=a[x].size(),v; 26 deep[x]=deep[fa]+1; f[x][0]=fa; 27 size[x]=1; 28 for (llg i=0;i<w;i++) 29 { 30 v=a[x][i]; 31 if (v==fa) continue; 32 dfs1(v,x); 33 size[x]+=size[v]; 34 sdown[x]+=sdown[v]+size[v]; 35 } 36 } 37 38 void dfs2(llg x,llg fa) 39 { 40 llg w=a[x].size(),v; 41 for (llg i=0;i<w;i++) 42 { 43 v=a[x][i]; 44 if (v==fa) continue; 45 sall[v]=sall[x]+n-2*size[v]; 46 dfs2(v,x); 47 } 48 } 49 50 void init() 51 { 52 llg x,y; 53 cin>>n>>T; 54 for (llg i=1;i<n;i++) 55 { 56 x=getint(),y=getint(); 57 a[x].push_back(y),a[y].push_back(x); 58 } 59 deep[1]=1; 60 dfs1(1,0); 61 sall[1]=sdown[1]; 62 dfs2(1,0); 63 for (llg j=1;j<=20;j++) 64 for (llg i=1;i<=n;i++) 65 f[i][j]=f[f[i][j-1]][j-1]; 66 } 67 68 llg find(llg x,llg y) 69 { 70 for (llg i=20;i>=0;i--) 71 if (deep[f[x][i]]>=deep[y]) 72 x=f[x][i]; 73 if (x==y) return x; 74 for (llg i=20;i>=0;i--) 75 if (f[x][i]!=f[y][i]) 76 x=f[x][i],y=f[y][i]; 77 return f[x][0]; 78 } 79 80 llg dis(llg x,llg y) 81 { 82 return deep[x]+deep[y]-deep[find(x,y)]*2; 83 } 84 85 llg up(llg x,llg res) 86 { 87 for (llg i=20;i>=0;i--) 88 if (res>=(1<<i)) 89 { 90 x=f[x][i]; 91 res-=(1<<i); 92 } 93 return x; 94 } 95 96 int main() 97 { 98 yyj("tree"); 99 init(); 100 while (T--) 101 { 102 llg x,y; 103 x=getint(),y=getint(); 104 if (deep[x]<deep[y]) swap(x,y); 105 double ans=dis(x,y)+1; 106 if (find(x,y)!=y) 107 { 108 ans+=(double)sdown[x]/(double)size[x]+(double)sdown[y]/(double)size[y]; 109 } 110 else 111 { 112 llg ne=up(x,deep[x]-deep[y]-1); 113 ans+=(double)sdown[x]/(double)size[x]+(double)(sall[y]-sdown[ne]-size[ne])/(double)(n-size[ne]); 114 } 115 printf("%.9lf\n",ans); 116 } 117 return 0; 118 }
本文作者:xrdog
作者博客:http://www.cnblogs.com/Dragon-Light/
转载请注明出处,侵权必究,保留最终解释权!