[AHOI2008]紧急集合 / 聚会
Posted yufenglin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[AHOI2008]紧急集合 / 聚会相关的知识,希望对你有一定的参考价值。
紧急集合 / 聚会
题目大意:
给出一个无向图,每一次给出图中的三个点,求离三个点距离之和最小的点。
解决方法:
倍增LCA。
首先我们两两点之间求出LCA,那么离他们距离之和最近的点就是三个点中深度最深的点,想一想为什么?
我们假设存在一个点离三个点距离之和更近且深度更浅,那么我们将它的深度往下走一个,一定会有两个点距离-1,一个点+1,所以往下移更靠近正解opt,那么我们就可以得出我们上述结论合法。
而关于距离之和,由于dis(u,v)=dep[u]+dep[v]-dep[lca(u,v)],那么我们把三个点两两之间∑一下再除以二就能得到答案了,式子就不推了。。。
dis=dep[x]+dep[y]+dep[z]-dep[lca(x,y)]-dis[lca(y,z)]-dis[lca(x,z)]
最后附上本题代码:
1 #include<cstdio> 2 #include<iostream> 3 #define maxn 500000 4 using namespace std; 5 6 int n,m,root,cnt; 7 int head[maxn+5],dep[maxn+5],f[maxn+5][30]; 8 bool vis[maxn+5]; 9 struct EDGE 10 { 11 int nxt,to; 12 }; 13 EDGE edge[maxn*2+5]; 14 15 int max(int x,int y) 16 { 17 if(dep[x]>=dep[y]) 18 { 19 return x; 20 } 21 return y; 22 } 23 int abs(int x) 24 { 25 if(x<0) 26 { 27 return -x; 28 } 29 return x; 30 } 31 void add(int x,int y) 32 { 33 edge[++cnt].to=y; 34 edge[cnt].nxt=head[x]; 35 head[x]=cnt; 36 } 37 void pre_fir(int u,int fa) 38 { 39 dep[u]=dep[fa]+1; 40 for(int i=0;i<=25;i++) 41 { 42 f[u][i+1]=f[f[u][i]][i]; 43 } 44 for(int i=head[u];i;i=edge[i].nxt) 45 { 46 if(edge[i].to==fa) 47 { 48 continue; 49 } 50 f[edge[i].to][0]=u; 51 pre_fir(edge[i].to,u); 52 } 53 } 54 int LCA(int x,int y) 55 { 56 if(dep[x]<dep[y]) 57 { 58 swap(x,y); 59 } 60 for(int i=25;i>=0;i--) 61 { 62 if(dep[f[x][i]]>=dep[y]) 63 { 64 x=f[x][i]; 65 } 66 if(x==y) 67 { 68 return x; 69 } 70 } 71 for(int i=25;i>=0;i--) 72 { 73 if(f[x][i]!=f[y][i]) 74 { 75 x=f[x][i]; 76 y=f[y][i]; 77 } 78 } 79 return f[x][0]; 80 } 81 int main() 82 { 83 scanf("%d%d",&n,&m); 84 for(int i=1;i<=n-1;i++) 85 { 86 int x,y; 87 scanf("%d%d",&x,&y); 88 add(x,y); 89 add(y,x); 90 vis[y]=1; 91 } 92 for(int i=1;i<=n;i++) 93 { 94 if(vis[i]==0) 95 { 96 root=i; 97 break; 98 } 99 } 100 dep[root]=1; 101 pre_fir(root,0); 102 for(int i=1;i<=m;i++) 103 { 104 int x,y,z; 105 scanf("%d%d%d",&x,&y,&z); 106 int ans1=LCA(x,y),ans2=LCA(y,z),ans3=LCA(x,z); 107 int ans=max(max(ans1,ans2),ans3); 108 printf("%d %d ",ans,dep[x]+dep[y]+dep[z]-dep[ans1]-dep[ans2]-dep[ans3]); 109 } 110 return 0; 111 }
以上是关于[AHOI2008]紧急集合 / 聚会的主要内容,如果未能解决你的问题,请参考以下文章
「AHOI2008」「LuoguP4281」紧急集合 / 聚会(LCA
luogu P4281 [AHOI2008]紧急集合 / 聚会 |LCA