bzoj1787: [Ahoi2008]Meet 紧急集合
lca。
3个点分别lca,可以知道,深度最深的lca就是答案。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 500000 + 10; const int maxm = 1000000 + 10; const int maxl = 22; int g[maxn],v[maxm],next[maxm],eid; int anc[maxn][maxl],h[maxn]; int q[maxn]; int A,B,C,n,m; void addedge(int a,int b) { v[eid]=b; next[eid]=g[a]; g[a]=eid++; v[eid]=a; next[eid]=g[b]; g[b]=eid++; } void build() { scanf("%d%d",&n,&m); memset(g,-1,sizeof(g)); for(int i=1,u,v;i<n;i++) { scanf("%d%d",&u,&v); addedge(u,v); } } void bfs() { int l,r,u; l=r=0; h[1]=1;q[r++]=1; anc[1][0]=1; while(l<r) { u=q[l++]; for(int i=g[u];~i;i=next[i]) if(v[i]!=anc[u][0]) { anc[v[i]][0]=u; q[r++]=v[i]; h[v[i]]=h[u]+1; } } } void up(int &a,int H) { for(int i=maxl-1;i>=0;i--) if(h[anc[a][i]]>=H) a=anc[a][i]; } int LCA(int a,int b) { if(h[a]!=h[b]) { if(h[a]>h[b]) up(a,h[b]); else up(b,h[a]); } if(a==b) return a; for(int l=maxl-1;l>=0;l--) if(anc[a][l]!=anc[b][l]) { a=anc[a][l]; b=anc[b][l]; } return anc[a][0]; } int dis(int a,int b) { int p=LCA(a,b); return h[a]+h[b]-2*h[p]; } void solve() { for(int i=1;i<=m;i++) { int p,p1,p2,p3; scanf("%d%d%d",&A,&B,&C); p1=LCA(A,B),p2=LCA(A,C),p3=LCA(B,C); if(p1==p2) p=p3; else if(p1==p3) p=p2; else p=p1; printf("%d %d\n",p,dis(p,A)+dis(p,B)+dis(p,C)); } } void predo() { bfs(); for(int i=1;i<maxl;i++) for(int u=1;u<=n;u++) anc[u][i]=anc[anc[u][i-1]][i-1]; } int main() { build(); predo(); solve(); return 0; }