题意是给出一棵无根树,对于每个询问
(x,y)
,输出以
x
为根的树中,
我们可以先以
1
为根处理出每个结点的最小/次小儿子编号和最小/次小后代编号。
对于一个询问
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+7;
const int INF=0x3f3f3f3f;
vector<int> adj[N];
int id[N],sz[N],mns[N],mnd[N],ses[N],sed[N],p[N],fa[N],tot=0;
bool sub(int x,int y ) { return id[x]>id[y]&&id[x]<id[y]+sz[y]; }
void dfs(int u,int pre)
{
id[u]=++tot;
fa[u]=pre;
sz[u]=1;
for(int v : adj[u])
{
if(v==pre) continue;
dfs(v,u);
sz[u]+=sz[v];
if(v<mns[u]) ses[u]=mns[u],mns[u]=v;
else if(v<ses[u]) ses[u]=v;
int mnv=min(mnd[v],v);
if(mnv<mnd[u]) sed[u]=mnd[u],mnd[u]=mnv,p[u]=v;
else if(mnv<sed[u]) sed[u]=mnv;
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,q;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;++i) adj[i].clear();
memset(mns,0x3f,sizeof(mns));
memset(ses,0x3f,sizeof(ses));
memset(mnd,0x3f,sizeof(mnd));
memset(sed,0x3f,sizeof(sed));
for(int i=1;i<n;++i)
{
int u,v;
scanf("%d%d",&u,&v);
adj[u].push_back(v);
adj[v].push_back(u);
}
tot=0;
dfs(1,0);
while(q--)
{
int x,y;
scanf("%d%d",&x,&y);
if(sz[y]==1) puts("no answers!");
else if(sub(x,y))
{
int ans1,ans2;
ans1=(sub(x,mns[y])||x==mns[y]?ses[y]:mns[y]);
ans2=(sub(x,p[y])||p[y]==x?sed[y]:mnd[y]);
if(y!=1) ans1=min(ans1,fa[y]),ans2=1;
if(ans1==INF&&ans2==INF) puts("no answers!");
else printf("%d %d\n",ans1,ans2);
}
else printf("%d %d\n",mns[y],mnd[y]);
}
puts("");
}
return 0;
}