一、Tarjan算法作用:
Tarjan算法是一种用于寻找图中节点的最近公共祖先(LCA)的算法。该算法通过深度优先搜索(DFS)遍历图,并使用并查集(Union-Find)数据结构来快速找到两个节点的最近公共祖先。
具体步骤如下:
1. 对图进行深度优先搜索(DFS),记录每个节点的深度和父节点。
2. 初始化并查集,将每个节点的父节点设置为自身。
3. 对每一对查询的节点(u, v),分别找到它们的根节点(即最终的祖先)。
4. 如果根节点相同,则它们的最近公共祖先就是该根节点;否则,将其中一个节点的根节点的父节点设置为另一个节点的根节点,然后重复此过程直到找到它们的最近公共祖先。Tarjan算法的时间复杂度为O(N+Qα(N)),其中N是节点数,Q是查询数,α是Ackermann函数的反函数,通常可以认为是一个很小的常数。因此,Tarjan算法是一种高效的方法来寻找图中节点的最近公共祖先。
二、LCA代码实现:
#include<bits/stdc++.h>
using namespace std;int n,m,root; //分别是点的数量、查询的数量、根节点
vector<int> e[10]; //点的邻接表
typedef pair<int,int> q;
vector<q> query[10];//存查询组
vector<int> fa;
vector<bool> vis;
vector<int> ans;int find_root(int i){if(i==fa[i]) return i;return fa[i]=find_root(fa[i]);
}void tarjan(int cur){vis[cur]=true;for(auto & it: e[cur]){if(!vis[it]){tarjan(it);fa[it]=cur;}}for(auto & it: query[cur]){if(vis[it.first]){ans[it.second]=find_root(fa[it.first]);}}
}int main(){cin >> n >> m >> root;fa.resize(n+1);ans.resize(n+1);vis.resize(n+1); // 注意这里应该是 n+1for(int i=1; i<=n; i++){fa[i]=i;}for(int i=1; i<=n-1; i++){ // 这里应该是 n-1 而不是 nint u,v;cin >> u >> v;e[u].push_back(v);e[v].push_back(u);}for(int i=1; i<=m; i++){int a,b;cin >> a >> b;query[a].push_back(q{b,i});query[b].push_back(q{a,i});}tarjan(root); // 这里应该传入根节点 rootfor(int i=1; i<=m; i++){cout << ans[i] << " ";}return 0;
}