Nearest Common Ancestors POJ - 1330(tarjan求lca离线算法模板)

题目:为了进入世界杯决赛圈,中国正在疯狂规划外援,但是足协要求外援必须要有中国血统。据了解在西班牙黄加马得李队效力的huxiaotaostasy和英国曼红队效力的yzm007有一个共同的中国血统的祖先Ginstein。现在足协已经草拟了一份规划球员名单和他们的祖先(这是一份庞大的名单追溯到所有球员的祖先女娲),足协想知道这份名单里任意两个人的公共祖先是谁

AC代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=1e5+5;
struct node{
	int v,nxt;
}e[maxn];
int head[maxn],tot,fa[maxn],vis[maxn],in[maxn];
int n,ansx,ansy; 
void init(){
	tot=1;
	memset(head,-1,sizeof(head));
	memset(vis,0,sizeof(vis));
	memset(in,0,sizeof(in));
}
inline void add(int u,int v){
	e[tot].v=v;
	e[tot].nxt=head[u];
	head[u]=tot++;
}
int find_x(int x){
	if(x==fa[x])return x;
	else return fa[x]=find_x(fa[x]);
}
void tarjan(int u){
	fa[u]=u;
	//vis[u]=1;
	for(int i=head[u];i!=-1;i=e[i].nxt){
		int v=e[i].v;
		tarjan(v);
		fa[v]=u;
	}
	vis[u]=1;//注意必须在回溯之后才标记vis[u],因为只有tarjan离线算法中的u代表相对较晚访问到的点。反过来想如果是回溯前的话,那答案一定是错的,可以自己手动模拟几遍 
	if(u==ansx&&vis[ansy])cout<<find_x(ansy)<<endl;
	if(u==ansy&&vis[ansx])cout<<find_x(ansx)<<endl;
}
int main(){
	ios::sync_with_stdio(false);
	int t;
	cin>>t;
	while(t--){
		init();
		cin>>n;
		for(int i=1;i<n;i++){
			int x,y;
			cin>>x>>y;
			add(x,y);
			in[y]++;
		}
		int root;
		for(int i=1;i<=n;i++){
			if(in[i]==0){
				root=i;
				break;
			}
		}
		cin>>ansx>>ansy;
		tarjan(root);
	}
} 
原创文章 38 获赞 7 访问量 1750

猜你喜欢

转载自blog.csdn.net/Alanrookie/article/details/106001685
今日推荐