传送门(洛谷)
这道题就是一个树上乘法原理
当有一个点是询问点p时:
s u m [ p ] + = 2 ∗ s i z e [ p ] − 1 , ( p , p ) 是 一 种 情 况 sum[p]+=2*size[p]-1,(p,p)是一种情况 sum[p]+=2∗size[p]−1,(p,p)是一种情况
当两个点都是询问点p的子树点的时候
设x有k棵子树
根据乘法原理,p有size[p]个点,则
s
u
m
[
p
]
+
=
∑
i
=
1
k
∑
j
=
1
k
s
i
z
e
[
s
o
n
[
i
]
]
∗
s
i
z
e
[
s
o
n
[
j
]
]
sum[p]+=\sum_{i=1}^k\sum_{j=1}^ksize[son[i]]*size[son[j]]
sum[p]+=∑i=1k∑j=1ksize[son[i]]∗size[son[j]]
=
∑
i
=
1
k
s
i
z
e
[
s
o
n
[
i
]
]
∗
(
s
i
z
e
[
p
]
−
1
)
=\sum_{i=1}^ksize[son[i]]*(size[p]-1)
=∑i=1ksize[son[i]]∗(size[p]−1)
=
(
s
i
z
e
[
p
]
−
1
)
∗
(
s
i
z
e
[
p
]
−
1
)
=(size[p]-1)*(size[p]-1)
=(size[p]−1)∗(size[p]−1)
但是如果是两个相同的点,则我们算重了一部分(子树大小不能乘以他自己的大小,也就是i=j时),应该减去:
∑
i
=
1
k
s
i
z
e
[
s
o
n
[
i
]
]
2
\sum_{i=1}^ksize[son[i]]^2
∑i=1ksize[son[i]]2
所以总答案为:
a
n
s
=
2
∗
s
i
z
e
[
p
]
−
1
+
(
s
i
z
e
[
p
]
−
1
)
∗
(
s
i
z
e
[
p
]
−
1
)
−
∑
i
=
1
k
s
i
z
e
[
s
o
n
[
i
]
]
2
ans=2*size[p]-1+(size[p]-1)*(size[p]-1)-\sum_{i=1}^ksize[son[i]]^2
ans=2∗size[p]−1+(size[p]−1)∗(size[p]−1)−i=1∑ksize[son[i]]2
=
(
s
i
z
e
[
p
]
)
2
−
∑
i
=
1
k
s
i
z
e
[
s
o
n
[
i
]
]
2
=(size[p])^2-\sum_{i=1}^ksize[son[i]]^2
=(size[p])2−i=1∑ksize[son[i]]2
#include<bits/stdc++.h>
#define mod 1000000007
#define rep(i,a,b) for(register int (i)=(a);(i)<=(b);(i)++)
#define don(i,a,b) for(register int (i)=(a);(i)>=(b);(i)--)
using namespace std;
const int maxn=1e5+10;
const int maxm=1e3+10;
int r,n,m,cnt=0;
int a[maxn],ans[maxn],vis[maxn],sum[maxn],head[maxn],siz[maxn];
template <class t> inline void read(t &x)
{
x=0;int f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=10*x+ch-'0';ch=getchar();}
x*=f;
}
template <class t> inline void write(t x) {
if(x<0) {putchar('-');x=~x+1;}
if(x>9) write(x/10);
putchar(x%10+48);
}
struct node{
int v,nex;
}e[maxn];
void add(int u,int v)
{
e[++cnt].v=v;
e[cnt].nex=head[u];
head[u]=cnt;
}
void readdata()
{
read(n);read(r),read(m);
rep(i,1,n-1) {
int x,y;
read(x),read(y);
add(x,y);
add(y,x);
}
}
inline void dfs(int x,int f) {
siz[x]=1;
for(int i=head[x];i;i=e[i].nex){
int xx=e[i].v;
if(xx==f) continue;
dfs(xx,x);
siz[x]+=siz[xx];
sum[x]+=siz[xx]*siz[xx];
}
ans[x]=(siz[x]*siz[x]-sum[x])%mod;
}
void work()
{
memset(siz,false,sizeof(siz));
dfs(r,0);
rep(i,1,m) {
int p;
read(p);
ans[p]%=mod;
write(ans[p]);
putchar('\n');
}
}
int main()
{
//freopen("input.txt","r",stdin);
readdata();
work();
return 0;
}