求三个结点到一个结点距离之和最小的结点以及距离和
求出两两lca,其中有两个相同,答案则为另一个
感觉就是一大暴力。。。
1 #include<algorithm> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<queue> 8 using namespace std; 9 10 #define N 500010 11 12 struct edge 13 { 14 int to,next; 15 }e[N<<2]; 16 int head[N<<2]; 17 int cnt; 18 19 int fa[N][20],dep[N]; 20 21 bool vis[N]; 22 23 int n,q; 24 int u,v,w; 25 int p1,p2,p3; 26 int t; 27 int ans; 28 29 void link(int x,int y) 30 { 31 e[++cnt]=(edge){x,head[y]}; 32 head[y]=cnt; 33 } 34 35 void dfs(int x) 36 { 37 vis[x]=1; 38 for (int i=1;i<=18;i++) 39 { 40 if (dep[x]<(1<<i)) 41 break; 42 fa[x][i]=fa[fa[x][i-1]][i-1]; 43 } 44 for (int i=head[x];i;i=e[i].next) 45 { 46 int t=e[i].to; 47 if (vis[t]) 48 continue; 49 dep[t]=dep[x]+1; 50 fa[t][0]=x; 51 dfs(t); 52 } 53 } 54 55 int lca(int x,int y) 56 { 57 if (dep[x]<dep[y]) 58 swap(x,y); 59 int t=dep[x]-dep[y]; 60 for (int i=18;i>=0;i--) 61 if (t & (1<<i)) 62 x=fa[x][i]; 63 if (x==y) 64 return x; 65 for (int i=18;i>=0;i--) 66 if (fa[x][i]!=fa[y][i]) 67 x=fa[x][i],y=fa[y][i]; 68 return fa[x][0]; 69 } 70 71 int dis(int x,int y) 72 { 73 int k=lca(x,y); 74 return dep[x]+dep[y]-(dep[k]<<1); 75 } 76 77 int main() 78 { 79 scanf("%d%d",&n,&q); 80 for (int i=1;i<n;i++) 81 { 82 scanf("%d%d",&u,&v); 83 link(u,v); 84 link(v,u); 85 } 86 dfs(1); 87 while (q--) 88 { 89 scanf("%d%d%d",&u,&v,&w); 90 p1=lca(u,v); 91 p2=lca(u,w); 92 p3=lca(v,w); 93 if (p1==p2) 94 t=p3; 95 else if (p1==p3) 96 t=p2; 97 else 98 t=p1; 99 ans=dis(u,t)+dis(v,t)+dis(w,t); 100 printf("%d %d\n",t,ans); 101 } 102 return 0; 103 }
时间: 2024-10-06 01:54:10