练练模板吧
这次是LCA模板
直接求三个点的LCA,然后会发现若有两个LCA相同,那么集合点为另一个点
然后我来证明一下为什么这样(口胡)
我们设lca(x,y)=hehe1,lca(x,z)=hehe2
那么非常显然lca(y,z)=lca(hehe1,z)=hehe2
然后假设hehe1到hehe2的距离为len
那么当我们把集合点从hehe2移到hehe1时与x,y的距离减去了2*len,与z的距离加上了len
那么显然hehe1更优
下面是代码(一开始RE了三四次,把cin改了就A,无语)
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
using namespace std;
const int N=600003;
struct edge{
int to,next;
}e[N*2+5];
int f[N][31],inn[N],head[N];
int dep[N],out[N];
int tot,n,m,x,y,z,p,q,r,s,ans,tim;
inline int read(){
char ch=getchar();
int f=1,x=0;
while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
inline void add(int x,int y){
e[++tot].to=y;
e[tot].next=head[x];
head[x]=tot;
}
void dfs(int fa,int x,int depth){
f[x][0]=fa;
dep[x]=depth;
inn[x]=++tim;
for(int i=head[x];i;i=e[i].next){
if(e[i].to!=fa){
dfs(x,e[i].to,depth+1);
}
}
out[x]=++tim;
}
bool pd(int x,int y){
return(inn[x]<=inn[y]&&out[x]>=out[y]);
}
int lca(int x,int y){
if(pd(x,y)){
return x;
}
if(pd(y,x)){
return y;
}
int k=x;
for(int j=30;j>=0;j--){
if(!pd(f[k][j],y)){
k=f[k][j];
}
}
return f[k][0];
}
int dis(int x,int y){
int t=lca(x,y);
return dep[x]+dep[y]-2*dep[t];
}
int main(){
n=read(),m=read();
for(int i=1;i<n;i++){
x=read(),y=read();
add(x,y);
add(y,x);
}
dfs(0,1,0);
f[1][0]=1;
for(int j=1;j<=30;j++){
for(int i=1;i<=n;i++){
f[i][j]=f[f[i][j-1]][j-1];
}
}
for(int i=1;i<=m;i++){
x=read();y=read();z=read();
int p1=lca(x,y),p2=lca(x,z),p3=lca(y,z),t;
if(p1==p2){
t=p3;
}else{
if(p2==p3){
t=p1;
}else{
t=p2;
}
}
int ans=dis(x,t)+dis(y,t)+dis(z,t);
printf("%d %d\n",t,ans);
}
return 0;
}
/*
in:
6 4
1 2
2 3
2 4
4 5
5 6
4 5 6
6 3 1
2 4 4
6 6 6
out:
5 2
2 5
4 1
6 0
*/