hdu5449 Robot Dog (树形dp+倍增lca)
(警告:本篇博客包含大量人类本质内容)
先处理出来lca,然后就只需要知道从每个点到他的父亲、和从他的父亲到这个点的期望时间就可以了
我们设f[x]为x到他父亲的期望时间;g[x]为从x的父亲到x的期望时间(注意到这两个是不一样的)
只考虑怎么算f,g是类似的
从某个点想走到他父亲时,情况会有:直接走到;先走到某个儿子然后走回来,再走到父亲;先走到某个儿子然后走回来,再走到某个儿子然后走回来,再走到某个儿子然后走回来,....,然后走到父亲
假设x有k个儿子,每个儿子记为ch[1...k]
那我们能得出$f[x]=\frac{1}{k+1}+\sum\limits_{i=1}^{k}{\frac{f[ch[i]]+1}{k+1}}+\frac{k}{k+1}(\frac{1}{k+1}+\sum\limits_{i=1}^{k}{\frac{f[ch[i]]+1}{k+1}}+\frac{k}{k+1}(...$
意思是,有$\frac{1}{k+1}$的可能性直接走到,另外$\frac{1}{k+1}$先用1时间走错到儿子、然后再用儿子的那个期望时间走回来,并以$\frac{k}{k+1}$的可能性再次有$\frac{1}{k+1}$的可能性直接走到,另外$\frac{1}{k+1}$先用1时间走错到儿子、然后再用儿子的那个期望时间走回来,并以$\frac{k}{k+1}$的可能性再次...
把$\frac{1}{k+1}+\sum\limits_{i=1}^{k}{\frac{f[ch[i]]+1}{k+1}}$记为a,$\frac{k}{k+1}$,就有$f[x]=a+b(a+b(a+b(a+b(....=(1+b^1+b^2+...)a=\frac{a}{1-b}$(等比数列和的极限)
这样dfs一下(好几下),就可以算出f了,g同理(注意顺序,两次dfs分别算f和g,算f的时候先算孩子,算g的时候先算父亲),只不过是有可能走错到父亲
然后倍增记一记f和g的和,做lca就行了(注意路径的方向)
然后就wa了...
可以发现其实这些期望都是整数,因为$\frac{1}{1-b}=k+1$,而a的分母又都是k+1...所以改用long long,避免掉奇奇怪怪的精度问题,就可以过了..(怀疑是%.4lf是否四舍五入的问题,我的本地是会四舍五入的所以拍不出锅,但要是直接截取就锅了...)
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 using namespace std; 5 typedef long long ll; 6 const int maxn=5e4+10; 7 8 inline ll rd(){ 9 ll x=0;char c=getchar();int neg=1; 10 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 11 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 12 return x*neg; 13 } 14 15 int eg[maxn*2][2],egh[maxn],ect; 16 int N,Q; 17 ll f[maxn][20],g[maxn][20]; 18 int fa[maxn][20],dep[maxn]; 19 20 inline void adeg(int a,int b){ 21 eg[++ect][0]=b;eg[ect][1]=egh[a];egh[a]=ect; 22 } 23 24 void dfs1(int x){ 25 int k=0; 26 for(int i=egh[x];i;i=eg[i][1]){ 27 int b=eg[i][0];if(b==fa[x][0]) continue; 28 dep[b]=dep[x]+1;fa[b][0]=x; 29 k++;dfs1(b); 30 } 31 if(fa[x][0]){ 32 ll alpha=1; 33 for(int i=egh[x];i;i=eg[i][1]){ 34 int b=eg[i][0];if(b==fa[x][0]) continue; 35 alpha+=f[b][0]+1; 36 } 37 f[x][0]=alpha; 38 } 39 40 } 41 42 void dfs2(int x){ 43 int k=0; 44 for(int i=egh[x];i;i=eg[i][1]){ 45 int b=eg[i][0];if(b==fa[x][0]) continue; 46 k++; 47 } 48 if(fa[x][0]){ 49 ll alpha=1; 50 for(int i=egh[x];i;i=eg[i][1]){ 51 int b=eg[i][0];if(b==fa[x][0]) continue; 52 alpha+=f[b][0]+1; 53 } 54 for(int i=egh[x];i;i=eg[i][1]){ 55 int b=eg[i][0];if(b==fa[x][0]) continue; 56 ll alphai=alpha-(f[b][0]+1); 57 alphai+=g[x][0]+1; 58 g[b][0]=alphai; 59 } 60 }else{ 61 ll alpha=1; 62 for(int i=egh[x];i;i=eg[i][1]){ 63 int b=eg[i][0];if(b==fa[x][0]) continue; 64 alpha+=f[b][0]+1; 65 } 66 for(int i=egh[x];i;i=eg[i][1]){ 67 int b=eg[i][0];if(b==fa[x][0]) continue; 68 double alphai=alpha-(f[b][0]+1); 69 g[b][0]=alphai; 70 } 71 } 72 for(int i=egh[x];i;i=eg[i][1]){ 73 int b=eg[i][0];if(b==fa[x][0]) continue; 74 dfs2(b); 75 } 76 // printf("%d %lf %lf\n",x,f[x][0],g[x][0]); 77 } 78 79 void getst(int x){ 80 for(int i=0;fa[x][i]&&fa[fa[x][i]][i];i++){ 81 fa[x][i+1]=fa[fa[x][i]][i]; 82 f[x][i+1]=f[x][i]+f[fa[x][i]][i]; 83 g[x][i+1]=g[x][i]+g[fa[x][i]][i]; 84 // printf("%d %d %d %lf %lf\n",x,i+1,fa[x][i+1],f[x][i+1],g[x][i+1]); 85 } 86 for(int i=egh[x];i;i=eg[i][1]){ 87 int b=eg[i][0];if(b==fa[x][0]) continue; 88 getst(b); 89 } 90 } 91 92 inline ll solve(int s,int t){ 93 ll re=0; 94 if(dep[s]>dep[t]){ 95 for(int i=18;i>=0;i--){ 96 if(fa[s][i]&&dep[fa[s][i]]>=dep[t]){ 97 re+=f[s][i],s=fa[s][i]; 98 } 99 } 100 // if(s==t) return re-f[s][0]; 101 }else if(dep[t]>dep[s]){ 102 for(int i=18;i>=0;i--){ 103 if(fa[t][i]&&dep[fa[t][i]]>=dep[s]){ 104 re+=g[t][i],t=fa[t][i]; 105 } 106 } 107 // if(s==t) return re-g[t][0]; 108 } 109 if(s==t) return re; 110 for(int i=18;i>=0;i--){ 111 if(fa[s][i]&&fa[t][i]&&fa[s][i]!=fa[t][i]){ 112 re+=f[s][i]+g[t][i]; 113 s=fa[s][i],t=fa[t][i]; 114 } 115 }re+=f[s][0]+g[t][0]; 116 return re; 117 } 118 119 int main(){ 120 // freopen("5449.in","r",stdin); 121 // freopen("5449.out","w",stdout); 122 int i,j,k; 123 for(int T=rd();T;T--){ 124 CLR(fa,0);CLR(dep,0);CLR(egh,0);ect=0; 125 CLR(f,0);CLR(g,0); 126 N=rd(); 127 for(i=1;i<N;i++){ 128 int a=rd()+1,b=rd()+1; 129 adeg(a,b);adeg(b,a); 130 } 131 dep[1]=1;dfs1(1);dfs2(1); 132 getst(1); 133 Q=rd(); 134 for(i=1;i<=Q;i++){ 135 int p=rd(),lst=rd()+1; 136 ll ans=0; 137 for(j=1;j<=p;j++){ 138 int now=rd()+1; 139 ans+=solve(lst,now); 140 lst=now; 141 } 142 printf("%lld.0000\n",ans); 143 } 144 if(T>1) printf("\n"); 145 } 146 return 0; 147 }