[概率][lca][dfs][树形dp] Jzoj P4225 宝藏
题解
- 这题一看似成相识,就是这题树的小改
- 具体做法之前的博客已经讲了很清楚了
- 那么这题的话,就直接把其所有询问存下来,按顺序跑就好了
- 对于它保留小数点后4位数,其实呢,这个东东就是个摆设,直接输出“.0000”就好了
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <cmath> 5 #define ll long long 6 #define N 1000010 7 using namespace std; 8 const ll mo=1e9+7; 9 struct edge {int to,from;}e[N*2]; 10 int n,q,head[N],cnt,T,Q,a[1010],lca; 11 ll sum,f[N][21],dep[N],ans,k1[N],k2[N]; 12 void insert(int x,int y) {e[++cnt].to=y; e[cnt].from=head[x]; head[x]=cnt;} 13 void dfs(int x,int fa) 14 { 15 f[x][0]=fa,dep[x]=dep[fa]+1,k1[x]=0; 16 for (int i=head[x];i;i=e[i].from) 17 if (e[i].to!=fa) 18 dfs(e[i].to,x),k1[x]=(k1[x]+k1[e[i].to]+1)%mo; 19 k1[x]=(k1[x]+1)%mo; 20 } 21 void dfs1(int x,int fa) 22 { 23 ll sum=0; 24 for (int i=head[x];i;i=e[i].from) if (e[i].to!=fa) sum=(sum+k1[e[i].to]+1)%mo; 25 else sum=(sum+k2[x]+1)%mo; 26 for (int i=head[x];i;i=e[i].from) 27 if (e[i].to!=fa) 28 k2[e[i].to]=((sum-k1[e[i].to])%mo+mo)%mo,dfs1(e[i].to,x); 29 } 30 void dfs2(int x,int fa) 31 { 32 k1[x]=(k1[x]+k1[fa])%mo,k2[x]=(k2[x]+k2[fa])%mo; 33 for (int i=head[x];i;i=e[i].from) if (e[i].to!=fa) dfs2(e[i].to,x); 34 } 35 int getlca(int u,int w) 36 { 37 if (dep[u]<dep[w]) swap(u,w); 38 int d=dep[u]-dep[w]; 39 if (d) for (int i=0;i<=log(n)/log(2)+1&&d;i++,d>>=1) if (d&1) u=f[u][i]; 40 if (u==w) return u; 41 for (int i=log(n)/log(2)+1;i>=0;i--) if (f[u][i]!=f[w][i]) u=f[u][i],w=f[w][i]; 42 return f[u][0]; 43 } 44 int main() 45 { 46 scanf("%d",&T); 47 while (T--) 48 { 49 scanf("%d",&n),memset(head,0,sizeof(head)),memset(k1,0,sizeof(k1)),memset(k2,0,sizeof(k2)),memset(f,0,sizeof(f)),memset(dep,0,sizeof(dep)); 50 for (int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),insert(u,v),insert(v,u); 51 dfs(1,-1),k1[1]=k2[1]=0,dfs1(1,-1),dfs2(1,-1); 52 for (int i=1;i<=log(n)/log(2)+1;i++) for (int j=1;j<=n;j++) f[j][i]=f[f[j][i-1]][i-1]; 53 scanf("%d",&Q); 54 while (Q--) 55 { 56 scanf("%d",&q),ans=0; 57 for (int i=1;i<=q+1;i++) scanf("%d",&a[i]); 58 for (int i=1;i<=q;i++) 59 lca=getlca(a[i],a[i+1]), 60 (ans+=(k1[a[i]]-k1[lca]+k2[a[i+1]]-k2[lca]+mo)%mo)%=mo; 61 printf("%.4lf\n",(double)ans); 62 } 63 printf("\n"); 64 } 65 }