CF123E Maze
子节点顺序被打乱,每个点可以回溯一次,每条边边权都为1,给你每个点为起点和终点的概率,问你我们访问这个树的期望长度
结论
若父亲为 x 要访问的节点为 y 显然 z 若在 y 前面则访问 y 的时候距离会加 2size[z] 并且这个概率时21 因此,父亲到儿子期望的走的距离为 sz[father] 或者是∑sz[son[t]]+1
此时我们记录在 t 子树中为起点的概率之和为 sum
这个点 t 为终点的概率为 y
那么答案就是 sum∗sz[t]∗y
不在这个子树中的同理,枚举每一个点为终点记录答案即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| #include<stdio.h> #include<iostream> #include<cmath> #include<cstring> #include<queue> #include<stack> #include<vector> #include<set> #include<map> #include<algorithm> #include<iomanip>
#define int long long
using namespace std;
const int maxn=100100;
double ans;
int n,m,head[maxn],size; int _x[maxn],_y[maxn]; int sz[maxn],val[maxn]; int xsum,ysum,f[maxn];
struct edge{ int next,to,lok; }e[maxn<<1];
inline void addedge(int next,int to) { e[++size].to=to; e[size].lok=next; e[size].next=head[next]; head[next]=size; }
void dfs(int t,int fat) { int i,j; sz[t]=1; f[t]=fat; for(i=head[t];i;i=e[i].next) { j=e[i].to; if(j==fat) continue; dfs(j,t); sz[t]+=sz[j]; val[t]+=val[j]; } }
signed main() { ios::sync_with_stdio(false); register int i,j; cin>>n; int t1,t2; for(i=1;i<n;i++) { cin>>t1>>t2; addedge(t1,t2); addedge(t2,t1); } for(i=1;i<=n;i++) { cin>>_x[i]>>_y[i]; xsum+=_x[i]; ysum+=_y[i]; val[i]=_x[i]; } dfs(1,0); for(i=1;i<=size;i++) { t1=e[i].lok; t2=e[i].to; if(f[t1]==t2) { ans+=((double)((n-sz[t1])*(xsum-val[t1]))/xsum)*((double)_y[t1])/ysum; } else { ans+=(double)(sz[t2]*((double)val[t2])/xsum)*(double)_y[t1]/ysum; } } cout<<fixed<<setprecision(9)<<ans<<endl; return 0; }
|