题目链接:http://acm.fzu.edu.cn/problem.php?pid=2207
比赛时这题感觉不会,赛后看了一下,其实并不是什么特别难的题目。
- 以节点1为根节点,找出每一个节点的父亲节点,保存在数组parent[]中。
- 对于任意两个节点,循环找出两个节点最近的根节点。(Find函数部分)
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1005;
const int INF=1<<30;
struct node
{
int v;
node* next;
}tree[N*2],*head[N*2];
int u,v,k;
int n,m;
int test;
int parent[N];
int tmp;
bool kk[N];
int vis[N];
int sum;//统计目标房间到根节点的最少经过房间数
void init()
{
tmp=0;
memset(parent,0,sizeof(parent));
memset(head,NULL,sizeof(head));
memset(vis,0,sizeof(vis));
}
void AddEdge(int u,int v)
{
tree[tmp].v=v;
tree[tmp].next=head[u];
head[u]=&tree[tmp++];
}
void dfs(int s)
{
node* p=head[s];
vis[s]=1;
while(p!=NULL)
{
if(!vis[p->v])
{
dfs(p->v);
parent[p->v]=s;
}
p=p->next;
}
}
int Find(int u,int v)
{
sum=0;
while(parent[u]>0)
{
kk[u]=true;
u=parent[u];
}
while(parent[v]>0)
{
if(kk[v])
return v;
v=parent[v];
sum++;
}
return 1;
}
int main()
{
cin>>test;
for(int ii=0;ii<test;ii++)
{
init();
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
AddEdge(u,v);
AddEdge(v,u);
}
dfs(1);//以1为根节点求出每个节点的父亲节点
printf("Case #%d:\n",ii+1);
for(int i=1;i<=m;i++)
{
for(int i=0;i<=n;i++)
kk[i]=0;
scanf("%d%d%d",&u,&v,&k);
int x=Find(u,v);
int ans1=1,ans2=0;
bool judge=false;
while(u!=x)
{
if(ans1==k)
{
judge=true;
cout<<u<<endl;
break;
}
u=parent[u];
ans1++;
}
if(judge)
continue;
k-=ans1;
k=sum-k;
while(ans2!=k)
{
v=parent[v];
ans2++;
}
cout<<v<<endl;
}
}
return 0;
}