洛谷4281 【AHOI2008】紧急集合/聚会(结论题)

版权声明:欢迎转载!请注明出处!qwq https://blog.csdn.net/g21glf/article/details/86610628

传送门

【题目分析】

为什么校内OJ树剖和倍增都被卡T两个点。。。。qwq

大力枚举+画图可以发现,答案一定是三个点的两两LCA中的一个,直接大力枚举就可以了。

详细的证明过程可以参考一下这篇博客:

传送门

【代码~】

#include<bits/stdc++.h>
using namespace std;
const int MAXN=5e5+10;
const int MAXM=1e6+10;

int n,q,cnt=1;
int a,b,c;
int head[MAXN],depth[MAXN],siz[MAXN],fa[MAXN],son[MAXN],top[MAXN];
int nxt[MAXM],to[MAXM];

int Read(){
	int i=0,f=1;
	char c;
	for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
	if(c=='-')
	  f=-1,c=getchar();
	for(;c>='0'&&c<='9';c=getchar())
	  i=(i<<3)+(i<<1)+c-'0';
	return i*f;
}

void add(int x,int y){
	nxt[cnt]=head[x];
	head[x]=cnt;
	to[cnt]=y;
	cnt++;
}

void dfs1(int u,int f){
	siz[u]=1;
	for(int i=head[u];i;i=nxt[i]){
		int v=to[i];
		if(v==f)
		  continue;
		depth[v]=depth[u]+1;
		fa[v]=u;
		dfs1(v,u);
		if(siz[v]>siz[son[u]])
		  son[u]=v;
	}
}

void dfs2(int u,int tp){
	top[u]=tp;
	if(!son[u])
	  return ;
	dfs2(son[u],tp);
	for(int i=head[u];i;i=nxt[i]){
		int v=to[i];
		if(v==fa[u]||v==son[u])
		  continue;
		dfs2(v,v);
	}
}

int lca(int x,int y){
	while(top[x]!=top[y]){
		if(depth[top[x]]<depth[top[y]])
		  swap(x,y);
		x=fa[top[x]];
	}
	return depth[x]<depth[y]?x:y;
}

void calc(){
	int lc1=lca(a,b),lc2=lca(a,c),lc3=lca(b,c);
	int sum=depth[a]+depth[b]+depth[c];
	int lcc1=lca(lc1,c),lcc2=lca(lc2,b),lcc3=lca(lc3,a);
	int ans1=sum-depth[c]-depth[lc1]*2;
	int ans2=sum-depth[b]-depth[lc2]*2;
	int ans3=sum-depth[a]-depth[lc3]*2;
	ans1+=depth[lc1]+depth[c]-depth[lcc1]*2;
	ans2+=depth[lc2]+depth[b]-depth[lcc2]*2;
	ans3+=depth[lc3]+depth[a]-depth[lcc3]*2;
	if(ans1<ans2){
		if(ans1<ans3){
			cout<<lc1<<' '<<ans1<<'\n';
			return ;
		}
		else{
			cout<<lc3<<' '<<ans3<<'\n';
			return ;
		}
	}
	else{
		if(ans2<ans3){
			cout<<lc2<<' '<<ans2<<'\n';
			return ;
		}
		else{
			cout<<lc3<<' '<<ans3<<'\n';
			return ;
		}
	}
}

int main(){
	n=Read(),q=Read();
	for(int i=1;i<n;++i){
		int x=Read(),y=Read();
		add(x,y),add(y,x);
	}
	dfs1(1,0),dfs2(1,1);
	while(q--){
		a=Read(),b=Read(),c=Read();
		calc();
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/g21glf/article/details/86610628