Tarjan离线求LCA模板

Tarjan 算法求 LCA 的时间复杂度为 O(n+q) ,是一种离线算法,要用到并查集。

ps:时间复杂度其实还需要考虑并查集操作的时间复杂度 ,但是由于在多数情况下,路径压缩并查集的单次操作复杂度可以看做 O(1),所以直接近似为 O(n+q) 。

const int MAXN = ;//最大点数 
 
pair<int,int> P[205];//存询问边
int lca[205];//存询问边对应的最近公共祖先 
//------------------------------------------------------------ 
struct Edge{//存树边 
	int to,next,w;//w为边权 
}E[MAXN*2];

int head[MAXN],tot;

inline void Add(int from,int to,int w){
	E[++tot].next = head[from];
	E[tot].to = to;
	E[tot].w = w;
	head[from] = tot;
	E[++tot].next = head[to];
	E[tot].to = from;
	E[tot].w = w;
	head[to] = tot;
}
//------------------------------------------------------------ 
struct Query{//存每个点对应的询问边
	int to,next,id;
}Q[405];

int headQ[MAXN],totq;

inline void AddQ(int from,int to,int id){ 
	Q[++totq].next = headQ[from];
	Q[totq].to = to;
	Q[totq].id = id;
	headQ[from] = totq;
	Q[++totq].next = headQ[to];
	Q[totq].to = from;
	Q[totq].id = id;
	headQ[to] = totq;
} 
//------------------------------------------------------------ 
bool vis[MAXN];
int fa[MAXN];//并查集祖先数组 

int Find(int x){
	if(fa[x] == x)return x;
	return fa[x] = Find(fa[x]);
}

void Union(int a,int b){
	int A = Find(a);
	int B = Find(b);
	if(A != B)fa[B] = A;
}

void Tarjan(int rt){
	vis[rt] = true;
	int to;
	for(int i=head[rt] ; i ; i=E[i].next){
		to = E[i].to;
		if(!vis[to]){
			Tarjan(to);
			Union(rt,to);
		}
	}
	for(int i=headQ[rt] ; i ; i=Q[i].next){
		to = Q[i].to;
		if(vis[to]){
			lca[Q[i].id] = Find(to);
		}
	}
}
//------------------------------------------------------------ 
inline void init(int n){
	for(int i=0 ; i<=n ; ++i)fa[i] = i;
	memset(vis,false,sizeof vis);
	memset(head,0,sizeof head);
	memset(headQ,0,sizeof headQ);
	tot = totq = 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值