solution
很明显,这道题就是要求,两个点之间的期望步数,那么我们知道,对于两个点x,y肯定是x走到lca再走下去到y 我们设f,g分别为由x走到他父亲的期望步数,和由父亲走来的期望步数 f[x]=1/deg[x]+
∑
u
∈
s
o
n
[
x
]
\sum_{u \in son[x]}
∑ u ∈ s o n [ x ] (f[u]+f[x]+1)/deg[x] g[x]=1/deg[fa[x]]+1/deg[fa[x]]*(g[x]+g[fa[x]]+1)+
∑
u
∈
s
o
n
[
x
]
a
n
d
u
!
=
x
\sum_{u \in son[x]and u!=x}
∑ u ∈ s o n [ x ] a n d u ! = x (f[u]+1+g[x])/deg[fa[x]] 简单解释下,g最后的那个转移,就是走到fa的一个非x的子节点,然后走上来,再走到x,总之都是在枚举第一步怎么走。 然后化简一下,f[x]两边同时乘上deg[x],然后右边的
∑
\sum
∑ f[u]=(deg[x]-1)*f[u] g同理 然后lca搞一下就没了。 Code
#include<cstdio>
#include<algorithm>
#include<cstring>
#define fo(i,a,b) for (int (i)=(a);(i)<=(b);(i)++)
#define fd(i,b,a) for (int (i)=(b);(i)>=(a);(i)--)
#define Fo(i,x) for (int i=head[x];i;i=next[i])
using namespace std;
typedef long long ll;
const int N=50000+55;
int head[N],to[N*2],next[N*2],d[N],h[N][21],tot,v,n,q,m;
int f[N],g[N],ans,deg[N];
void R(int &n)
{
int t=0,p=1;char ch;
for(ch=getchar();!('0'<=ch && ch<='9');ch=getchar())
if(ch=='-') p=-1;
for(;'0'<=ch && ch<='9';ch=getchar()) t=t*10+ch-'0';
n=t*p;
}
void add(int x,int y){
to[++tot]=y;
next[tot]=head[x];
head[x]=tot;
}
void dfsf(int x){
Fo(i,x){
int v=to[i];
if (v==h[x][0]) continue;
h[v][0]=x;d[v]=d[x]+1;
dfsf(v);
f[x]+=f[v];
}
f[x]=(f[x]+deg[x]);
}
void dfsg(int x){
int sum=0;
Fo(i,x) {
int v=to[i];
if (v!=h[x][0])
sum+=f[v];
}
Fo(i,x){
int v=to[i];
if (v==h[x][0]) continue;
g[v]=g[x]+deg[x]+sum-f[v];
dfsg(v);
}
}
void dfs(int x){
Fo(i,x){
int v=to[i];
if (v==h[x][0]) continue;
f[v]+=f[x];
g[v]+=g[x];
dfs(v);
}
}
int lca(int x,int y){
if (d[x]<d[y]) swap(x,y);
fd(k,20,0)
if (d[h[x][k]]>d[y]) x=h[x][k];
if (d[x]!=d[y]) x=h[x][0];
fd(k,20,0)
if (h[x][k]!=h[y][k]) x=h[x][k],y=h[y][k];
if (x==y) return x;
return h[x][0];
}
int main(){
freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
int T;
R(T);
while (T--){
tot=0;
memset(head,0,sizeof(head));
memset(deg,0,sizeof(deg));
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
R(n);
int x,y,k;
fo(i,1,n-1){
R(x);R(y);
x++;y++;
add(x,y);add(y,x);deg[x]++;deg[y]++;
}
h[x][0]=1;
dfsf(1);
f[1]=0;
dfsg(1);
dfs(1);
fo(j,1,20)
fo(i,1,n)
h[i][j]=h[h[i][j-1]][j-1];
int p;
int a[501];
R(q);
while (q--)
{
scanf("%d",&p);
fo(i,0,p) scanf("%d",&a[i]),a[i]++;
ans=0;
for (int i=1;i<=p;i++)
{
int l=lca(a[i-1],a[i]);
ans+=f[a[i-1]]-f[l]+g[a[i]]-g[l];
}
printf("%d.0000\n",ans);
}
printf("\n");
}
return 0;
}