【 lca 】最近公共祖先

时光总嘲笑我的痴心妄想 提交于 2019-11-27 14:56:31

 

  • Step1 Problem:

[原题] 给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。

  • Step2 Ideas:

lca模板题,主要为了存模板。LCA(Least Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先

  • Step3 Code: Tarjan,离线算法,时间复杂度O(n + q)

  1 // luogu-judger-enable-o2
  2 #define _CRT_SECURE_NO_WARNINGS
  3 #include<cstdio>
  4 #include<iostream>
  5 #include<cstring>
  6 #include<algorithm>
  7 #include<bitset>
  8 #include<cassert>
  9 #include<cctype>
 10 #include<math.h>
 11 #include<cstdlib>
 12 #include<ctime>
 13 #include<deque>
 14 #include<iomanip>
 15 #include<list>
 16 #include<map>
 17 #include<queue>
 18 #include<set>
 19 #include<stack>
 20 #include<vector>
 21 #define lt k<<1
 22 #define rt k<<1|1
 23 #define lowbit(x) x&(-x)
 24 #define lson l,mid,lt
 25 #define rson mid+1,r,rt
 26 using namespace std;
 27 typedef long long  ll;
 28 typedef long double ld;
 29 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
 30 #define mem(a, b) memset(a, b, sizeof(a))
 31 //#define int ll
 32 const double pi = acos(-1.0);
 33 const double eps = 1e-6;
 34 const double C = 0.57721566490153286060651209;
 35 const ll mod = 3e7;
 36 const int inf = 0x3f3f3f3f;
 37 const ll INF = 0x3f3f3f3f3f3f3f3f;
 38 const int maxn = 5e5+ 4000;
 39 struct node {
 40     int u, v, w, next;
 41     node () {}
 42     node(int u_, int v_, int w_, int next_) {
 43         u = u_;
 44         v = v_;
 45         w = w_;
 46         next = next_;
 47     }
 48 } edge[maxn << 1];
 49 
 50 struct nod {
 51     int u, v, id, next;
 52     nod() {}
 53     nod(int u_, int v_, int id_, int next_) {
 54         u = u_;
 55         v = v_;
 56         id = id_;
 57         next = next_;
 58     }
 59 }qu[maxn << 1];
 60 int n, m, ans;
 61 int head[maxn], head1[maxn];
 62 int cnt, cnt1;
 63 int res[maxn];
 64 int de[maxn], pre[maxn], fa[maxn];
 65 bool vis[maxn];
 66 
 67 void init() {
 68     cnt = cnt1 = 0;
 69     mem(vis, false);
 70     mem(de, 0);
 71     mem(head, -1);
 72     mem(head1, -1);
 73     mem(qu, 0);
 74     mem(edge, 0);
 75     for (int i = 1; i <= n; i++) fa[i] = i;
 76 }
 77 
 78 void add_edge(int u, int v, int w) {
 79     edge[cnt] = (node){ u, v, w, head[u] };
 80     head[u] = cnt++;
 81 }
 82 
 83 void add_qu(int u, int v, int id) {
 84     qu[cnt1] = (nod){ u, v, id, head1[u] };
 85     head1[u] = cnt1++;
 86 }
 87 
 88 int find_fa(int x) {
 89     if (x == fa[x]) return x;
 90     else return fa[x] = find_fa(fa[x]);
 91 }
 92 
 93 void Tarjan(int u) {
 94     vis[u] = true;
 95     for (int i = head[u]; ~i; i = edge[i].next) {
 96         int v = edge[i].v;
 97         if (!vis[v]) {
 98             Tarjan(v);
 99             int r1 = find_fa(u);
100             int r2 = find_fa(v);
101             if (r1 != r2) fa[r2] = r1;
102         }
103     }
104     for (int i = head1[u]; ~i; i = qu[i].next) {
105         int v = qu[i].v;
106         if (vis[v]) res[qu[i].id] = find_fa(v);
107     }
108 }
109 
110 int main() {
111 //    freopen("testdata.in", "r", stdin);
112     int s;
113     cin >> n >> m >> s;
114     init();
115     for (int i = 1; i < n; i++) {
116         int u, v;
117         cin >> u >> v;
118         add_edge(u, v, 1);
119         add_edge(v, u, 1);
120     }
121     for (int i = 1; i <= m; i++) {
122         int a, b;
123         cin >> a >> b;
124         add_qu(a, b, i);
125         add_qu(b, a, i);
126     }
127     Tarjan(s);
128     for (int i = 1; i <= m; i++) cout << res[i] << endl;
129     return 0;
130 }
  • Step4 Code2: 倍增法求lca,在线算法,时间复杂度O(n logn)

  1 #define _CRT_SECURE_NO_WARNINGS
  2 #include<cstdio>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<bitset>
  7 #include<cassert>
  8 #include<cctype>
  9 #include<math.h>
 10 #include<cstdlib>
 11 #include<ctime>
 12 #include<deque>
 13 #include<iomanip>
 14 #include<list>
 15 #include<map>
 16 #include<queue>
 17 #include<set>
 18 #include<stack>
 19 #include<vector>
 20 #define lt k<<1
 21 #define rt k<<1|1
 22 #define lowbit(x) x&(-x)
 23 #define lson l,mid,lt
 24 #define rson mid+1,r,rt
 25 using namespace std;
 26 typedef long long  ll;
 27 typedef long double ld;
 28 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
 29 #define mem(a, b) memset(a, b, sizeof(a))
 30 //#define int ll
 31 const double pi = acos(-1.0);
 32 const double eps = 1e-6;
 33 const double C = 0.57721566490153286060651209;
 34 const ll mod = 3e7;
 35 const int inf = 0x3f3f3f3f;
 36 const ll INF = 0x3f3f3f3f3f3f3f3f;
 37 const int maxn = 5e5+ 4000;
 38 int lg[maxn], dep[maxn], fa[maxn][20], head[maxn];
 39 int cnt;
 40 int n, m, s;
 41 
 42 struct node {
 43     int v, next;
 44 } edge[maxn << 1];
 45 
 46 void add_edge(int u, int v) {
 47     edge[cnt].v = v;
 48     edge[cnt].next = head[u];
 49     head[u] = cnt++;
 50 }
 51 
 52 void init() {
 53     cnt = 0;
 54     for (int i = 1; i <= n; i++) {
 55         head[i] = -1;
 56         dep[i] = -1;
 57         lg[i] = lg[i - 1] + (1 << (lg[i - 1]) == i);
 58     }
 59     mem(fa, 0);
 60 }
 61 
 62 void dfs(int u, int fath) {
 63     dep[u] = dep[fath] + 1;
 64     fa[u][0] = fath;
 65     for (int i = 1; (1 << i) <= dep[u]; i++) {
 66         fa[u][i] = fa[fa[u][i - 1]][i - 1];
 67     }
 68     for (int i = head[u]; ~i; i = edge[i].next) {
 69         if (edge[i].v != fath) dfs(edge[i].v, u);
 70     }
 71 }
 72 
 73 int lca(int u, int v) {
 74     if (dep[u] < dep[v]) swap(u, v);
 75     while (dep[u] > dep[v]) u = fa[u][lg[dep[u] - dep[v]] - 1];
 76     if (u == v) return u;
 77     for (int i = lg[dep[u]] - 1; i >= 0; i--) {
 78         if (fa[u][i] != fa[v][i]) {
 79             u = fa[u][i];
 80             v = fa[v][i];
 81         }
 82     }
 83     return fa[u][0];
 84 }
 85 
 86 int main() {
 87     scanf("%d%d%d", &n, &m, &s);
 88     init();
 89     for (int i = 1; i < n; i++) {
 90         int u, v;
 91         cin >> u >> v;
 92         add_edge(u, v);
 93         add_edge(v, u);
 94     }
 95     dfs(s, 0);
 96     for (int i = 1; i <= m; i++) {
 97         int u, v;
 98         scanf("%d%d", &u, &v);
 99         printf("%d\n", lca(u, v));
100     }
101     return 0;
102 }

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!