zoukankan      html  css  js  c++  java
  • 【 lca 】最近公共祖先

    • 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
    ", lca(u, v));
    100     }
    101     return 0;
    102 }
  • 相关阅读:
    lua 学习
    IOS表情存入MYSQL数据库失败
    C# string数组转int数组
    打开端口
    win10下设置IIS、安装php7.2
    NET Core 应用程序 IIS 运行报错 502.3-Gateway
    微信小程序(一)--简单的介绍
    C#socket通信
    使用VScode 的插件
    Vue学习笔记:Slot
  • 原文地址:https://www.cnblogs.com/zyysyang/p/11367457.html
Copyright © 2011-2022 走看看