0
点赞
收藏
分享

微信扫一扫

#10136. 「一本通 4.4 练习 3」聚会

就是耍帅 2022-03-12 阅读 50

loj
还是有一点不清楚的

  1. 为什么三个点最近的集合点是深度最大的lca
  2. 为啥dfs过程中有些代码换了位置就不对了
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e6;
int e[2*N+10],nx[2*N+10],h[2*N+10],cnt=0,f[N][25];
int deep[N+10],vis[N+10];
void add(int x,int y)
{
	e[cnt]=y,nx[cnt]=h[x],h[x]=cnt++;
}
/*void dfs(int x,int fa)
{
	int i;
	vis[x]=1;
//	deep[x]=deep[fa]+1;
	for(i=1; i<=20; i++)
		f[x][i]=f[f[x][i-1]][i-1];  
	for(i=h[x]; ~i; i=nx[i])
	{
		int j=e[i];  这些代码不太清楚
		if(vis[j])
			continue;
		if(j==fa)
			continue;
			if(!deep[j])
		deep[j]=deep[x]+1;
		f[j][0]=x;
		deep[j]=1;
		dfs(j,x);
	}
}*/
void dfs(int u,int fa)
{
	deep[u]=deep[fa]+1;
vis[u]=1;
	f[u][0]=fa;
	for(int i=0; i<=20; i++)
		f[u][i+1]=f[f[u][i]][i];
	for(int i=h[u]; i!=-1; i=nx[i])
		{
	int v=e[i];
		if(vis[v]) continue;
		dfs(v,u);
	}
}
int lca(int x,int y)
{
	int i;
	if(deep[x]<deep[y])
		swap(x,y);
	for(i=20; i>=0; i--)
	{
		if(deep[f[x][i]]>=deep[y])
		{
			x=f[x][i];
		}
		if(x==y)
			return x;
	}
	for(i=20; i>=0; i--)
	{
		if(f[x][i]!=f[y][i])
		{
			x=f[x][i];
			y=f[y][i];
		}
	}
	return f[x][0];
}
int main()
{
	int i,j,k,m,n;
	memset(h,-1,sizeof(h));
	scanf("%d%d",&n,&m);
	for(i=1; i<n; i++)
	{
		int a,b;
		cin>>a>>b;
		add(a,b),add(b,a);
	}
//	deep[1]=1;
//	deep[1]=1;
	dfs(1,1);
	for(i=1; i<=m; i++)
	{
		int a,b,c;
		cin>>a>>b>>c;
		int x=lca(a,b);
		int y=lca(a,c);//分别求出三个点的lca  找出两个相同的lca 一定是深度较小的那个 所以集合点就是另外一个
		int z=lca(b,c);
		int ans;
		if(x==y)
			ans=z;
		else if(x==z)
			ans=y;
		else
			ans=x;
//		printf("++++ %d %d %d\n",x,y,z);
公式 但是我不理解
		printf("%d %d\n",ans,deep[a]+deep[b]+deep[c]-deep[x]-deep[y]-deep[z]);
	}
	return 0;
}
举报

相关推荐

0 条评论