hihocoder1067 最近公共祖先·二

思路:

使用tarjan算法,这是一种离线算法。

实现:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef pair<int, int> pii;
 4 const int MAXN = 100005;
 5 vector<int> G[MAXN], qry[MAXN];
 6 int par[MAXN], vis[MAXN];
 7 void init(int n)
 8 {
 9     for (int i = 0; i <= n; i++) par[i] = i;
10 }
11 int find(int x)
12 {
13     if (par[x] == x) return par[x];
14     return par[x] = find(par[x]);
15 }
16 int uni(int x, int y)
17 {
18     x = find(x); y = find(y);
19     if (x == y) return x;
20     par[x] = y; return y;
21 }
22 void dfs(int u, int f, map<pii, int> & ans)
23 {
24     vis[u] = 1;
25     for (auto it: qry[u])
26     {
27         int tmp = vis[it];
28         if (!tmp) continue;
29         if (tmp == 1)
30             ans[pii(u, it)] = it;
31         else if (tmp == 2)
32             ans[pii(u, it)] = find(it);
33     }
34     for (int i = 0; i < G[u].size(); i++)
35         if (!vis[G[u][i]]) dfs(G[u][i], u, ans);
36     vis[u] = 2;
37     uni(u, f);
38 }
39 int main()
40 {
41     int n, q;
42     cin >> n;
43     string x, y;
44     map<string, int> mp;
45     map<int, string> mp2;
46     int id = 1, root = -1;
47     for (int i = 0; i < n; i++)
48     {
49         cin >> x >> y;
50         int pid = -1, sid = -1;
51         if (!mp.count(x)) { mp[x] = pid = id; mp2[id] = x; id++; }
52         else pid = mp[x];
53         if (!mp.count(y)) { mp[y] = sid = id; mp2[id] = y; id++; }
54         else sid = mp[y];
55         if (i == 0) root = pid;
56         G[pid].push_back(sid);
57     }
58     cin >> q;
59     vector<pii> v;
60     for (int i = 0; i < q; i++)
61     {
62         cin >> x >> y;
63         int xid = mp[x], yid = mp[y];
64         qry[xid].push_back(yid);
65         qry[yid].push_back(xid);
66         v.push_back(pii(xid, yid));
67     }
68     init(n);
69     map<pii, int> ans;
70     dfs(root, 0, ans);
71     for (auto it: v)
72     {
73         int xid = it.first, yid = it.second;
74         pii a(xid, yid), b(yid, xid);
75         if (ans.count(a)) cout << mp2[ans[a]] << endl;
76         else cout << mp2[ans[b]] << endl;
77     }
78     return 0;
79 }

 

转载于:https://www.cnblogs.com/wangyiming/p/9166644.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值