不错的题,就是找lca呗。
因为三个点,所以一定在三个点连接的树枝上,那么先两个求个lca,第三个再走到这里就可以了。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#define maxn 500010
using namespace std;
int next[2*maxn],to[2*maxn],head[maxn],dep[maxn],fa[maxn][21];
int n,m,num,T;
void addedge(int x,int y)
{
num++;to[num]=y;next[num]=head[x];head[x]=num;
}
void dfs(int x)
{
for (int p=head[x];p;p=next[p])
if (to[p]!=fa[x][0])
{
fa[to[p]][0]=x;
dep[to[p]]=dep[x]+1;
dfs(to[p]);
}
}
int go_up(int x,int d)
{
for (int i=0;i<=20;i++)
if (d&(1<<i)) x=fa[x][i];
return x;
}
int LCA(int x,int y)
{
if (dep[x]>dep[y]) x=go_up(x,dep[x]-dep[y]);
else y=go_up(y,dep[y]-dep[x]);
if (x==y) return x;
for (int i=20;i>=0;i--)
if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int main()
{
scanf("%d%d",&n,&T);
for (int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
addedge(x,y);addedge(y,x);
}
dep[1]=0;fa[1][0]=0;
dfs(1);
for (int j=1;j<=20;j++)
for (int i=1;i<=n;i++)
if (fa[i][j-1]) fa[i][j]=fa[fa[i][j-1]][j-1];
else fa[i][j]=0;
while (T--)
{
int a,b,c,ans,id,lca1,lca2,sum;
scanf("%d%d%d",&a,&b,&c);
lca1=LCA(a,b);sum=dep[a]-dep[lca1]+dep[b]-dep[lca1];
lca2=LCA(lca1,c);sum+=dep[lca1]-dep[lca2]+dep[c]-dep[lca2];
ans=sum,id=lca1;
lca1=LCA(b,c);sum=dep[b]-dep[lca1]+dep[c]-dep[lca1];
lca2=LCA(lca1,a);sum+=dep[lca1]-dep[lca2]+dep[a]-dep[lca2];
if (sum<ans) ans=sum,id=lca1;
lca1=LCA(a,c);sum=dep[a]-dep[lca1]+dep[c]-dep[lca1];
lca2=LCA(lca1,b);sum+=dep[lca1]-dep[lca2]+dep[b]-dep[lca2];
if (sum<ans) ans=sum,id=lca1;
printf("%d %d\n",id,ans);
}
return 0;
}