Problem Description
小茗同学最近在认真地准备比赛,所以经常玩以撒的结合。
《以撒的结合》是一款由Edmund McMillen,Florian Himsl 开发,并由Edmund McMillen最早于2011年09月29日发行的一款2D平面角色扮演、动作冒险类的独立游戏。游戏的角色将在有着能够提升能力的道具与特殊技能的半RPG世界中闯荡。
——来自百度百科
小茗同学在打BOSS前,费掉了很多HP。在地图的一些房间里有补充HP的红心,然而小茗同学受到了看不见地图的诅咒。凭借不知道哪里来的记忆,小茗同学记得某个有红心的房间在房间A与房间B的路上的第K个房间里。为了简化问题,我们把地图看成一棵树。小茗同学想知道A到B的第K个房间号为多少,由于小茗同学很累,所以现在这个任务交给你了。
Input
第一行是一个整数T(T<=10),表示有T组测试数据。
每组数据的第一行为两个整数n m(0 < n< 1000,0< m <= n*n),分别表示房间个数和询问次数。
接下来n-1行,每行两个整数u v(0 < u、v<=n,且u≠v),表示地图上房间u和房间v有一条路径。
最后是m行,每行三个整数u v k,表示询问房间u到房间v的路径上的第k个房间。
输入数据保证合法,即k不超过u、v的最短距离。
Output
对于每组数据,首先第一行先输出“Case #x:“ ,其中x是从1开始,表示数据组号,接下来m行,每行输出相应的房间号。
Sample Input
1
6 3
1 2
2 4
2 5
1 3
3 6
4 6 4
1 6 2
4 5 3
Sample Output
Case #1:
3
3
5
题解:
先求出lca后,根据大小关系判断k在哪边就好。记录路径更便于输出。
代码:
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std;
const int N=1e3+10;
int cnt,u,v,k,tot,n,q,t;
int dep[N],fa[N][N],siz[N],son[N];
struct node{int to,next;}edge[N<<2];
int head[N<<2];
void add(int u,int v)
{
edge[cnt].to=v,edge[cnt].next=head[u],head[u]=cnt++;
edge[cnt].to=u,edge[cnt].next=head[v],head[v]=cnt++;
}
void dfs1(int u,int f,int d)
{
fa[u][0]=u;
for(int i=1;i<=d;i++)
{
fa[u][i]=fa[f][i-1];
}
dep[u]=d,siz[u]=1,son[u]=0;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(v==f)continue;
dfs1(v,u,d+1);
siz[u]+=siz[v];
if(siz[son[u]]<siz[v]) son[u]=v;
}
}
int top[N],pre[N],tree[N];
void dfs2(int u,int tp)
{
top[u]=tp,tree[u]=++tot,pre[tree[u]]=u;
if(!son[u]) return ;
dfs2(son[u],tp);
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(v==fa[u][1]||v==son[u]) continue;
dfs2(v,v);
}
}
void init()
{
tot=0;
cnt=0;
memset(head,-1,sizeof(head));
memset(fa,0,sizeof(fa));
}
int lca(int x,int y)
{
int fx=top[x],fy=top[y];
while(fx!=fy)
{
if(dep[fx]<dep[fy]) swap(x,y),swap(fx,fy);
x=fa[fx][1],fx=top[x];
}
if(dep[x]>dep[y]) swap(x,y);
return x;
}
int main()
{
scanf("%d",&t);
for(int o=1;o<=t;o++)
{
printf("Case #%d:\n",o);
init();
scanf("%d%d",&n,&q);
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
}
dfs1(1,0,1),dfs2(1,1);
while(q--)
{
scanf("%d%d%d",&u,&v,&k);
int lc=lca(u,v);
if(k==1)
{
printf("%d\n",u);
}
else if(dep[u]+dep[v]-2*dep[lc]+1==k)
{
printf("%d\n",v);
}
else if(dep[u]-dep[lc]+1>=k)
{
printf("%d\n",fa[u][k-1]);
}
else
{
int kk=dep[u]+dep[v]-2*dep[lc]-k+1;
printf("%d\n",fa[v][kk]);
}
}
}
}