LCA求调(找不同即可)
查看原帖
LCA求调(找不同即可)
420137
一月气聚楼主2022/2/3 20:28
//这是刚打的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int N=500001;
int f[N][20],n,m,s,en,dep[N];
int lg[N],first[N];
struct edge{
	int nxt,to;
}ed[N*2];//因为是无向图,还有反向边 

int jianbian(int u,int v){
	ed[++en].nxt=first[u];
	ed[en].to=v;
	first[u]=en;
}

void dfs(int now,int fath){
	f[now][0]=fath; dep[now]=dep[fath]+1; 
	for(int i=1; i<=lg[dep[now]]; ++i)//核心 
		f[now][i] = f[f[now][i-1]][i-1];
	for(int i=first[now]; i ; i=ed[i].nxt){
		if(ed[i].to!=fath) dfs(ed[i].to,now);
	}
}

int LCA(int x,int y){
	if(dep[x]<dep[y]) swap(x,y);
	while(dep[x] > dep[y])
	  x=f[x][lg[dep[x]-dep[y]]-1];
	if(x==y) return x;
	for(int i=lg[dep[x]]-1; i>=0; i--){
		if(f[x][i]!=f[y][i])
		  x=f[x][i],y=f[y][i];
	}
	return f[x][0];
}

int main()
{
	scanf("%d%d%d",&n,&m,&s);
	for(int i=1;i<n;++i){
		int x,y;
		scanf("%d%d",&x,&y);
		jianbian(x,y); jianbian(y,x);
	}
	for(int i=1;i<=n;++i)
	  lg[i]=lg[i-1]+((1<<lg[i-1]) ==i);
	dfs(s,0);
	for(int i=1;i<=m;++i){
		int a,b;
		scanf("%d%d",&a,&b);
		printf("%d\n",LCA(a,b));
	}
	return 0;
}

为什么我和原来写的几乎完全一样却全RE呢?

//这是原来的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 500001

using namespace std;

int n,m,s,en;
int first[maxn];
struct edge{
	int nxt,e;
}ed[maxn*2];
int fa[maxn][20];//fa[i][j]:i结点向上2^j级祖先 
int depth[maxn];//每个结点的深度
int lg[maxn];
                                    
void jianbian(int s,int e){
	ed[++en].e=e;
	ed[en].nxt=first[s];
	first[s]=en;
}
/*想要实现这个算法,首先我们要记录各个点的深度和他们2^i级的的祖先,
  用数组depth表示每个节点的深度,fa[i][j]表示节点i的2^j级祖先。*/
void dfs(int now,int fath)
{
	fa[now][0]=fath; depth[now]=depth[fath]+1;
	for(int i=1; i<=lg[depth[now]]; ++i)
	  fa[now][i] = fa[fa[now][i-1]][i-1];//核心
	                //意思是now的2^i祖先等于now的2^(i-1)祖先的2^(i-1)祖先 
	                //这里就是倍增的思想 
	for(int i = first[now]; i ; i = ed[i].nxt)
	  if(ed[i].e!=fath) dfs(ed[i].e,now);
}

int LCA(int x,int y){
	if(depth[x] < depth[y]) swap(x,y);
	while(depth[x] > depth[y])
	  x=fa[x][lg[depth[x]-depth[y]]-1];
	if(x==y) return x;
	for(int i=lg[depth[x]]-1; i>=0 ; --i)
		if(fa[x][i]!=fa[y][i]) //因为我们要跳到它们LCA的下面一层,所以它们肯定不相等,如果不相等就跳过去。
		  x=fa[x][i],y=fa[y][i];//相等就是过了,要往回收,这次就不加了 
	return fa[x][0];
}

int main()
{
	scanf("%d%d%d",&n,&m,&s);
	for(int i=1;i<n;++i){
		int x,y;
		scanf("%d%d",&x,&y);
		jianbian(x,y); jianbian(y,x);
	}
	for(int i=1;i<=n;++i)
	  lg[i]=lg[i-1]+((1<<lg[i-1]) ==i);
	dfs(s,0);
	for(int i=1;i<=m;++i){
		int a,b;
		scanf("%d%d",&a,&b);
		printf("%d\n",LCA(a,b));
	}
	return 0;
}
2022/2/3 20:28
加载中...