给你一棵树,求三个点到哪个点的距离和最近,且求出距离
挺好证的,是三个LCA中矮的那个,
但是这题需要卡常技巧,QAQ
以后还是要养成加上卡常技巧的习惯,20分啊
#include<cstdio> #include<cstdlib> #include<vector> using namespace std; int n,m; const int N=500003; int tot,head[N]; struct node { int v,nx; }e[N<<1]; void add(int u,int v) { e[++tot].v =v,e[tot].nx =head[u],head[u]=tot; e[++tot].v =u,e[tot].nx =head[v],head[v]=tot; } int fa[N][20],dep[N]; inline int read() { int x=0;char c=getchar(); while(c<‘0‘ || c>‘9‘) c=getchar(); while(c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+c-‘0‘,c=getchar(); return x; } void dfs(int rt,int f) { dep[rt]=dep[f]+1; fa[rt][0]=f; for(int i=1;i<20 && fa[rt][i-1];i++) fa[rt][i]=fa[fa[rt][i-1]][i-1]; for(int i=head[rt];i;i=e[i].nx ) if(e[i].v !=f) dfs(e[i].v ,rt); } int LCA(int x,int y) { if(dep[x]<dep[y]) x+=y,y=x-y,x-=y; int dis=dep[x]-dep[y]; for(int i=1,j=0;i<=dis;i<<=1,j++) if(dis&i) x=fa[x][j]; if(x==y) return x; for(int i=19;~i;i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return fa[x][0]; } int main() { n=read(),m=read(); int u,v,w; for(int i=1;i<n;i++) u=read(),v=read(),add(u,v); dfs(1,0); while(m--) { u=read(),v=read(),w=read(); int a=LCA(u,v),b=LCA(u,w),c=LCA(v,w); int ans=dep[u]+dep[v]+dep[w],pos; if(dep[a]==dep[b] ) ans-=dep[a]*2+dep[c],pos=c; else if(dep[a]==dep[c]) ans-=dep[a]*2+dep[b],pos=b; else ans-=dep[b]*2+dep[a],pos=a; printf("%d %d\n",pos,ans); } return 0; }
原文:https://www.cnblogs.com/xwww666666/p/11668461.html