B:A Problem about Tree
-
总时间限制:
- 1000ms 内存限制:
- 65536kB
-
描述
-
Given a tree with Nvertices and N- 1 edges, you are to answer Qqueries on "which vertex isY's parent if we choose Xas the root of the entire tree?".
输入
-
The first line of input is an integer T, the number of test cases.
The first line of each test case contains N(2 ≤ N ≤ 10000) and Q(1 ≤ Q ≤ 10000).
Each of the following N - 1 lines of the test case contains two integers a(1 ≤ a ≤ N) and b(1 ≤b ≤ N) indicating an edge between a and b.
Each of the following Q lines of the test case contains two integers X(1 ≤ X ≤ N) and Y(1 ≤ Y≤ N, Y ≠ X) indicating an query.
输出
-
For each query, output the Y's parent if X is the root of tree.
样例输入
-
1 5 3 1 2 1 3 4 3 3 5 2 3 4 1 5 2
样例输出
-
1 3 1
题意:n个节点的一棵树,m次询问:求以x为根y的父亲节点。
思路:lca倍增算法。利用bfs求出每个节点的深度以及2^i倍祖先。接下来求x和y的lca,如果lca!=y,那么y的父节点就是ancestor[y][0],不然求x的depth[x]-depth[y]-1祖先结点。画图还是比较看粗来的,详见程序:
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN=10000+100;
int n,m,edge_cnt;
int head[MAXN],ancestor[MAXN][15],depth[MAXN];
struct Edge
{
int v;
int next;
}edge[2*MAXN];
void init()
{
edge_cnt=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v)
{
edge[edge_cnt].v=v;
edge[edge_cnt].next=head[u];
head[u]=edge_cnt++;
}
void bfs(int root)
{
queue<int>Q;
ancestor[root][0]=root; depth[root]=0;
Q.push(root);
while(!Q.empty())
{
int u=Q.front(); Q.pop();
for(int i=1;i<15;i++)
ancestor[u][i]=ancestor[ancestor[u][i-1]][i-1];
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(v==ancestor[u][0])
continue;
depth[v]=depth[u]+1; ancestor[v][0]=u;
Q.push(v);
}
}
}
int lca(int x,int y)
{
if(depth[x]<depth[y]) swap(x,y);
for(int i=0;i<15;i++)
if((depth[x]-depth[y])&(1<<i)) x=ancestor[x][i];
if(x==y)
return x;
for(int i=14;i>=0;i--)
if(ancestor[x][i]!=ancestor[y][i])
x=ancestor[x][i],y=ancestor[y][i];
return ancestor[x][0];
}
int main()
{
//freopen("text.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
init();
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v); addedge(v,u);
}
bfs(1);
while(m--)
{
int x,y;
scanf("%d%d",&x,&y);
int fa=lca(x,y);
if(fa==y)
{
int D=depth[x]-depth[y]-1;
while(D)
{
int k=(int)(log10(1.0*D)/log10(2.0));
x=ancestor[x][k];
D-=(1<<k);
}
printf("%d\n",x);
}
else
printf("%d\n",ancestor[y][0]);
}
}
return 0;
}