Timofey has an apple tree growing in his garden; it is a rooted tree of n vertices with the root in vertex 1 (the vertices are numbered from 1 to n). A tree is a connected graph without loops and multiple edges.
This tree is very unusual — it grows with its root upwards. However, it's quite normal for programmer's trees.
The apple tree is quite young, so only two apples will grow on it. Apples will grow in certain vertices (these vertices may be the same). After the apples grow, Timofey starts shaking the apple tree until the apples fall. Each time Timofey shakes the apple tree, the following happens to each of the apples:
Let the apple now be at vertex u.
- If a vertex u has a child, the apple moves to it (if there are several such vertices, the apple can move to any of them).
- Otherwise, the apple falls from the tree.
It can be shown that after a finite time, both apples will fall from the tree.
Timofey has q assumptions in which vertices apples can grow. He assumes that apples can grow in vertices x and y, and wants to know the number of pairs of vertices (a, b) from which apples can fall from the tree, where a — the vertex from which an apple from vertex x will fall, b — the vertex from which an apple from vertex y will fall. Help him do this.
Input
The first line contains integer t (1≤t≤10^4) — the number of test cases.
The first line of each test case contains integer n (2≤n≤2⋅10^5) — the number of vertices in the tree.
Then there are n−1 lines describing the tree. In line i there are two integers ui and vi (1≤ui,vi≤n, ui≠vi) — edge in tree.
The next line contains a single integer q (1≤q≤2⋅10^5) — the number of Timofey's assumptions.
Each of the next q lines contains two integers xi and yi (1≤xi,yi≤n) — the supposed vertices on which the apples will grow for the assumption i.
It is guaranteed that the sum of n does not exceed 2⋅10^5. Similarly, It is guaranteed that the sum of q does not exceed 2⋅10^5.
Output
For each Timofey's assumption output the number of ordered pairs of vertices from which apples can fall from the tree if the assumption is true on a separate line.
题意:有n个节点,n-1条边,1是根节点,每个节点最多两个子节点,其中有2个苹果在点上,他会进入子节点,如果他下面有两个子节点,那么会进入任意一个,问你q次,每次a,b表示两个苹果所在的节点,问最终两个苹果落点有多少种不同可能。
解析:如果点a到底部有x种方案,点b到底部有y种方案,那么总方案数就是x*y。而对于点u,他的方案数取决于子节点的分叉数,因此我们需要自下而上更新父节点的方案贡献值。
注意:题中输入是无向边,但是规定1是根节点,因此需要自己递归求一下每个点的子节点和父节点到底是谁。如果每次都暴力更新到根节点,那么会超时,因此我们还需要记录层数,从下一层一层向上,这样每个点就只会遍历一次。
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
typedef long long ll;
int n,mx,fa[N];//mx表示最大达到层数,fa表示该点的父节点是谁
vector<int> edge[N],son[N],levle[N];
bool st[N];//判断已经遍历过
ll w[N];//表示该点到底部有几种选择
void dfs(int u,int f,int lev)//当前点u,父亲f,层数lev
{
son[f].push_back(u);//加入子节点
fa[u]=f;//记录父节点
mx=max(mx,lev);//更新最大深度
st[u]=true,levle[lev].push_back(u);//该层存入该点
for(int i=0;i<edge[u].size();i++)
{
int j=edge[u][i];
if(!st[j]) dfs(j,u,lev+1);//防止回搜
}
}
void init()
{
for(int i=0;i<=mx;i++) levle[i].erase(levle[i].begin(),levle[i].end());
mx=0;
for(int i=0;i<=n;i++)
{
st[i]=false;
w[i]=0;
edge[i].erase(edge[i].begin(),edge[i].end());
son[i].erase(son[i].begin(),son[i].end());
}
}
void solve()
{
scanf("%d",&n);
init();
for(int i=1;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
edge[a].push_back(b);
edge[b].push_back(a);
}
dfs(1,0,1);
for(int i=1;i<=n;i++) if(!son[i].size()) w[i]=1;//没儿子就是最底层
for(int i=mx;i>=2;i--)//自下往上更新w
{
for(int j=0;j<levle[i].size();j++)
{
int u=levle[i][j];
int f=fa[u];//父节点
w[f]+=w[u];
}
}
int q;
scanf("%d",&q);
while(q--)
{
int a,b;
scanf("%d%d",&a,&b);
printf("%lld\n",w[a]*w[b]);
}
}
int main()
{
int t=1;
scanf("%d",&t);
while(t--) solve();
return 0;
}