Tarjan离线求LCA模板

版权声明:本文为博主原创文章,转载请附上注明就行_(:з」∠)_。 https://blog.csdn.net/vocaloid01/article/details/82081526

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;
}

猜你喜欢

转载自blog.csdn.net/vocaloid01/article/details/82081526