题解:
显然集合点为lca(x,y).lca(y,z),lca(z,x)中的一个
然后暴力计算即可
lca倍增即可
代码:
#include<bits/stdc++.h> using namespace std; const int N=1e6+5,K=20; int x,y,num,n,m,zz[N],f[K][N],z,fi[N],deep[N],l,out[N],in[N],ne[N]; void dfs(int x,int y) { in[x]=++l; f[0][x]=y; for (int i=fi[x];i;i=ne[i]) if (y!=zz[i]) { deep[zz[i]]=deep[x]+1; dfs(zz[i],x); } out[x]=++l; } void jb(int x,int y) { ne[++num]=fi[x]; fi[x]=num; zz[num]=y; } int pd(int x,int y) { return in[x]<=in[y]&&out[x]>=out[y]; } int lca(int x,int y) { if (x==y)return x; if (deep[x]<deep[y])swap(x,y); for (int i=19;i>=0;i--) if (f[i][x]!=0&&!pd(f[i][x],y))x=f[i][x]; return f[0][x]; } int main() { scanf("%d%d",&n,&m); for (int i=1;i<n;i++) { scanf("%d%d",&x,&y); jb(x,y);jb(y,x); } deep[1]=1; dfs(1,0); for (int i=1;i<K;i++) for (int j=1;j<=n;j++)f[i][j]=f[i-1][f[i-1][j]]; while (m--) { scanf("%d%d%d",&x,&y,&z); int x1=lca(x,y),x2=lca(y,z),x3=lca(x,z); int s1=deep[x]+deep[y]-deep[x1]; int s2=deep[y]+deep[z]-deep[x2]; int s3=deep[x]+deep[z]-deep[x3]; int y1=lca(x1,z),y2=lca(x,x2),y3=lca(x3,y); s1+=deep[z]-2*deep[y1],s2+=deep[x]-2*deep[y2],s3+=deep[y]-2*deep[y3]; int ans=x1,num=s1; if (s2<num) { num=s2; ans=x2; } if (s3<num) { num=s3; ans=x3; } printf("%d %d\n",ans,num); } }