LCA 最近公共祖先 模板

版权声明:https://blog.csdn.net/huashuimu2003 https://blog.csdn.net/huashuimu2003/article/details/84643244

Lca 离线算法(tarjan算法) 模板

#include<bits/stdc++.h>
#define _ 1000100
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc(){return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++;}
inline int read()
{
	int x=0,f=1;  char ch=getc();
	while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getc();}
	while(isdigit(ch))  {x=(x<<1)+(x<<3)+(ch^48);  ch=getc();}
	return x*f;
}
void put(int x)
{
	if(x==0){putchar('0');putchar('\n');return;}
	if(x<0){putchar('-');x=-x;}
	int num=0;char ch[16];
	while(x) ch[++num]=x%10+'0',x/=10;
	while(num) putchar(ch[num--]);
	putchar('\n');
}
int ver1[_],Next1[_],link1[_];
int ver2[_],Next2[_],link2[_],id[_];
int tot=0,n,m,ans[_],fa[_],vis[_];
inline void add1(int x,int y)
{
	ver1[++tot]=y,Next1[tot]=link1[x],link1[x]=tot;
}
inline void add2(int x,int y,int t)
{
	ver2[++tot]=y,Next2[tot]=link2[x],link2[x]=tot,id[tot]=t;
}
int get(int x)
{
	if(fa[x]==x)return x;
	return fa[x]=get(fa[x]);
}
void Lca(int x)
{
	vis[x]=1;
	for(int i=link1[x];i;i=Next1[i])
	{
		int y=ver1[i];
		if(vis[y]) continue;
		Lca(y);
		fa[y]=x;
	}
	for(int i=link2[x];i;i=Next2[i])
	{
		int y=ver2[i];
		if(vis[y])
			ans[id[i]]=get(y);
	}
}
int main()
{
	n=read();m=read();
	for(int i=1;i<n;++i)
	{
		int x=read(),y=read();
		add1(x,y),add1(y,x);
	}
	tot=0;
	for(int i=1;i<=m;++i)
	{
		int x=read(),y=read();
		add2(x,y,i),add2(y,x,i);
	}
	for(int i=1;i<=n;++i)
		fa[i]=i;
	Lca(1);
	for(int i=1;i<=m;++i)
		put(ans[i]);
	return 0;
}

Lca 树上倍增 模板

抄算法竞赛进阶指南上的模板

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
	int f=1,num=0;
	char ch=getchar();
	while (ch<'0'||ch>'9') { if (ch=='-') f=-1; ch=getchar(); }
	while (ch>='0'&&ch<='9') num=(num<<1)+(num<<3)+ch-'0', ch=getchar();
	return num*f;
}
const int SIZE=50010;
int f[SIZE][20],d[SIZE],dist[SIZE];
int ver[SIZE*2],Next[SIZE*2],edge[SIZE*2],head[SIZE];
int T,n,m,tot,t;
queue<int>q;
void add(int x,int y,int z)
{
	ver[++tot]=y,edge[tot]=z,Next[tot]=head[x],head[x]=tot;
}
void bfs()
{//预处理 
	q.push(1);
	d[1]=1;
	while (!q.empty())
	{
		int x=q.front();
		q.pop();
		for (int i=head[x];i;i=Next[i])
		{
			int y=ver[i];
			if (d[y]) continue;
			d[y]=d[x]+1;
			dist[y]=dist[x]+edge[i];
			f[y][0]=y;
			for (int j=1;j<=t;j++)
				f[y][j]=f[f[y][j-1]][j-1];
			q.push(y);
		}
	}
}
int lca(int x,int y)//回答一个询问 
{
	if (d[x]<d[y]) swap(x,y);
	for (int i=t;i>=0;i--)
		if (d[f[y][i]]>=d[x]) y=f[y][i];
	if (x==y) return x;
	for (int i=t;i>=0;i--)
		if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
	return f[x][0];
}
int main()
{
	T=read();
	while (T--)
	{
		n=read(),m=read();
		t=(int)(log(n)/log(2))+1;
		//清空 
		for (int i=1;i<=n;++i)
			head[i]=d[i]=0;
		tot=0;
		//读入一棵树 
		for (int i=1;i<n;++i)
		{
			int x=read(),y=read(),z=read();
			add(x,y,z),add(y,x,z);
		}
		bfs();
		//回答问题 
		for (int i=1;i<=m;++i)
		{
			int x=read(),y=read();
			printf("%d\n",dist[x]+dist[y]-2*dist[lca(x,y)]);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/huashuimu2003/article/details/84643244
今日推荐