hihoCoder week15 最近公共祖先·二
tarjan求lca 就是dfs序中用并查集维护下,当访问到询问的第二个点u的时候 lca就是第一点的find(fa[v])
fa[v] = u; // 当v为u的儿子 且 v已经dfs完毕
#include <bits/stdc++.h> using namespace std; const int N = 2e5+10; struct node { int to; int nxt; int lca; }E[N]; int n, cnt, tot, fa[N], vis[N]; map<string ,int> mp; string s[N], s1, s2; vector<int> son[N]; int head[N], ans[N]; void add_edge(int u,int v) { ++tot; E[tot].to = v; E[tot].nxt = head[u]; head[u] = tot; } void init() { for(int i=0; i<N; i++) fa[i] = i; } int fi(int x) { return fa[x] == x ? x : fa[x] = fi(fa[x]); } int getId(string str) { if(mp[str]) { return mp[str]; } mp[str] = (++cnt); s[cnt] = str; return cnt; } void dfs(int u) { for(int i=0; i<son[u].size(); i++) { int v = son[u][i]; if(vis[v]) continue; dfs(v); fa[v] = u; } vis[u] = true; for(int i=head[u]; i!=0; i=E[i].nxt) { int v = E[i].to; if(!vis[v]) continue; if(i%2) { E[i].lca = fi(v); E[i+1].lca = E[i].lca; } else { E[i].lca = fi(v); E[i-1].lca = E[i].lca; } } } int main() { freopen("in.txt","r",stdin); init(); int n; scanf("%d", &n); for(int i=0; i<n; i++) { cin >> s1 >> s2; int u = getId(s1); int v = getId(s2); son[u].push_back(v); } int m; scanf("%d", &m); for(int i=0; i<m; i++) { cin >> s1 >> s2; int u = getId(s1); int v = getId(s2); add_edge(u,v); add_edge(v,u); } dfs(1); for(int i=1;i<=m;i++) { cout << s[E[i*2].lca] <<endl; } return 0; }