给无根一棵树,有边权,有两种询问,一种给出两个点,问这两个点的距离是多少,另一个,给给三个点,a,b,k,问从a开始到b的路径的第k个点是的编号是多少。
显然lca,关于第二询问,我们还是要求一下,这两个点的lca,因为我们要选择一个点往上倍增的去寻找第k个点,但是,万一x就是lca,x不能往上跳着找,所以,我们要交换一下,从a数第k个,相当于从b数第(路劲总点数-k+1)个,,
然而我的板子有问题,好垃圾,手生看了板子,像去年都可以自己敲出来,变垃圾了。无限wa了以后,才发现板子有问题。。。心态爆炸。。。貌似以前写的ac的lca也有问题?以前是用dfs写的。。。应该来讲也没什么问题。。。这次用bfs写了。。。
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#define maxn 10005
using namespace std;
int head[maxn],to[maxn<<1],_next[maxn<<1],w[maxn<<1];
int edge;
void addEdge(int x,int y,int z)
{
to[++edge]=y,w[edge]=z,_next[edge]=head[x],head[x]=edge;
to[++edge]=x,w[edge]=z,_next[edge]=head[y],head[y]=edge;
}
queue<int>que;
int dis[maxn];
int d[maxn];
int f[maxn][15];
int N;
void bfs()
{
que.push(1);d[1]=1;
dis[1]=0;
while(que.size())
{
int x=que.front();que.pop();
for(int i=head[x];i;i=_next[i])
{
int y=to[i];
if(d[y])continue;
d[y]=d[x]+1;
dis[y]=dis[x]+w[i];
f[y][0]=x;
for(int j=1;j<=N;j++)
f[y][j]=f[f[y][j-1]][j-1];
que.push(y);
}
}
}
int lca(int x,int y)
{
if(d[x]>d[y])swap(x,y);
for(int i=N;i>=0;i--)
if(d[f[y][i]]>=d[x])y=f[y][i];
if(x==y)return x;
for(int i=N;i>=0;i--)
if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
return f[x][0];
}
int n;
void init()
{
edge=0;
memset(head,0,sizeof(head));
memset(d,0,sizeof(d));
N=(int)log2(n)+1;
}
int main()
{
int t;cin>>t;
while(t--)
{
cin>>n;
init();
int x,y,z;
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
addEdge(x,y,z);
}
bfs();
char c[10];
for(;;)
{
scanf("%s",c);
if(c[1]=='O')break;
if(c[1]=='I')
{
scanf("%d%d",&x,&y);
printf("%d\n",dis[x]+dis[y]-2*dis[lca(x,y)]);
}
else
{
scanf("%d%d%d",&x,&y,&z);
int r=lca(x,y);
int tot=d[x]+d[y]-2*d[r]+1;
if(d[x]-d[r]+1<z)
{
swap(x,y);
z=tot-z+1;
}
int now=x;
int cnt=1;
int p=0,_2=1;
while(cnt!=z)
{
if(cnt+_2<=z)
{
cnt+=_2;
now=f[now][p];
p++,_2*=2;
}
else
{
p--;_2/=2;
}
}
printf("%d\n",now);
}
}
}
return 0;
}