2016-06-22
这个题就是找树中三个点到哪个点距离和最短,很明显是LCA,找这三个点两两之间的LCA,画个图看一下就行,很简单。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<queue> 7 #define ll long long 8 #define M 1000009 9 using namespace std; 10 ll read() 11 { 12 char ch=getchar(); 13 ll x=0,f=1; 14 for(;ch<'0'||ch>'9';ch=getchar()) 15 if(ch=='-') 16 f=-1; 17 for(;ch>='0'&&ch<='9';ch=getchar()) 18 x=x*10+ch-'0'; 19 return x*f; 20 } 21 int n,m,cnt,h[M],head[M],next[M],u[M],lc[M][22]; 22 void jia(int a1,int a2) 23 { 24 next[++cnt]=head[a1]; 25 head[a1]=cnt; 26 u[cnt]=a2; 27 } 28 void dfs(int x) 29 { 30 for(int i=1;(1<<i)<=h[x];i++) 31 lc[x][i]=lc[lc[x][i-1]][i-1]; 32 for(int i=head[x];i;i=next[i]) 33 if(u[i]!=lc[x][0]) 34 { 35 h[u[i]]=h[x]+1; 36 lc[u[i]][0]=x; 37 dfs(u[i]); 38 } 39 } 40 int lca(int a1,int a2) 41 { 42 if(h[a1]<h[a2]) 43 swap(a1,a2); 44 int a3=h[a1]-h[a2]; 45 for(int i=0;i<=20;i++) 46 if(a3&(1<<i)) 47 a1=lc[a1][i]; 48 for(int i=20;i>=0;i--) 49 if(lc[a1][i]!=lc[a2][i]) 50 { 51 a1=lc[a1][i]; 52 a2=lc[a2][i]; 53 } 54 if(a1==a2) 55 return a1; 56 return lc[a1][0]; 57 } 58 int main() 59 { 60 n=read(); 61 m=read(); 62 for(int i=1;i<n;i++) 63 { 64 int a1=read(),a2=read(); 65 jia(a1,a2); 66 jia(a2,a1); 67 } 68 dfs(1); 69 for(int i=1;i<=m;i++) 70 { 71 int a1=read(),a2=read(),a3=read(),a4; 72 int t1=lca(a1,a2),t2=lca(a1,a3),t3=lca(a2,a3); 73 if(h[t2]<h[t1]) 74 printf("%d %d ",t1,h[a1]+h[a2]-h[t1]+h[a3]-2*h[t2]); 75 else 76 { 77 if(h[t2]>h[t3]) 78 a4=t2; 79 else 80 a4=t3; 81 printf("%d %d ",a4,h[a1]+h[a2]-2*h[t1]+h[a3]-h[a4]); 82 } 83 } 84 return 0; 85 }