最近公共祖先离线算法Tarjan
一篇解释的很好的博客:
http://www.cnblogs.com/JVxie/p/4854719.html
poj 1330
题目传送门:http://poj.org/problem?id=1330
模板代码:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
typedef long long int LL;
using namespace std;
const int MAXN = 10010;
vector<int>query[MAXN];
vector<int>ma[MAXN];
int fa[MAXN];
int rnk[MAXN];
int ans;
bool vis[MAXN];
int ance[MAXN]; ///祖先
void init(int n){
for(int i=0;i<=n;i++)
fa[i]=i;
ans=0;
memset(ance,0,sizeof(ance));
memset(vis,false,sizeof(vis));
for(int i=0;i<=n;i++)
ma[i].clear();
for(int i=0;i<=n;i++)
query[i].clear();
}
int Find(int x){
return x==fa[x]?fa[x]:Find(fa[x]);
}
void Union(int x,int y){
x=Find(x);
y=Find(y);
fa[y]=x;
}
void Tarjan(int x){
for(int i=0;i<ma[x].size();i++){
Tarjan(ma[x][i]);
Union(x,ma[x][i]);
ance[Find(x)]=x;
}
vis[x]=true;
for(int i=0;i<query[x].size();i++){
if(vis[query[x][i]])
ans=ance[Find(query[x][i])];
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
init(n);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
vis[v]=true;
ma[u].push_back(v);
}
int root;
for(int i=1;i<=n;i++){
if(!vis[i]) {
root=i;break;
}
}
memset(vis,false,sizeof(vis));
int p,q;
scanf("%d%d",&p,&q);
query[p].push_back(q);
query[q].push_back(p);
Tarjan(root);
printf("%d\n",ans);
}
}
vj上公共祖先的练习题:
练习题链接https://vjudge.net/contest/218876#problem/G