考虑只有两个人的情况
集合点可以是树上两点间路径上的任一点
总长度可以用LCA求出
ans=dep[ x ] - dep[ LCA(x,y) ] + dep[ y ] - dep[ LCA(x,y) ]
三个人也差不多
Ans=dep[ x ] - dep[ LCA(x,y) ] + dep[ y ] - dep[ LCA(y,z) ] + dep[ z ] - dep[ LCA(x,z) ]
集合点就是三个LCA中深度最大的点
这个可以自己画个图就知道了
然后套LCA模板就好了
#include<iostream> #include<cstring> #include<cmath> #include<cstdio> #include<algorithm> using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } const int N=5e5+7; int n,m; int fir[N],from[N<<1],to[N<<1],cnt; inline void add(int &a,int &b) { from[++cnt]=fir[a]; fir[a]=cnt; to[cnt]=b; } int dep[N],f[N][19]; void dfs(int &x)//预处理 { for(int i=1;(1<<i)<=dep[x];i++) f[x][i]=f[f[x][i-1]][i-1]; for(int i=fir[x];i;i=from[i]) { int &v=to[i]; if(v==f[x][0]) continue; f[v][0]=x; dep[v]=dep[x]+1; dfs(v); } } int LCA(int x,int y)//LCA模板 { if(dep[x]<dep[y]) swap(x,y); for(int i=18;i>=0;i--) if(dep[f[x][i]]>=dep[y]) x=f[x][i]; if(x==y) return x; for(int i=18;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; return f[x][0]; } void query(int &x,int &y,int &z)//询问 { int fx=LCA(x,y),fy=LCA(y,z),fz=LCA(x,z); int fa= dep[fx]>dep[fy] ? fx : fy; fa= dep[fa] > dep[fz] ? fa : fz; printf("%d ",fa);//集合点是3个LCA中最深的点 printf("%d ",dep[x]+dep[y]+dep[z]-dep[fx]-dep[fy]-dep[fz]); } int main() { int a,b,c; n=read(); m=read(); for(int i=1;i<n;i++) { a=read(); b=read(); add(a,b); add(b,a); } int root=1; f[1][0]=1; dep[1]=1; dfs(root); for(int i=1;i<=m;i++) { a=read(); b=read(); c=read(); query(a,b,c); } return 0; }