• LCA专题


    先上模板~

    /*
        LCA(倍增法,二分搜索):rt[i][u](i<D=20) 表示u的第2^i的祖先
        LCA预处理复杂度O (logn),每次询问O (logn)
        DFS中要记录点的深度以及它的父亲,(dep[u] = d; rt[0][u] = fa;)
    */
    int LCA(int u, int v)   {
        if (dep[u] < dep[v])    swap (u, v);
        for (int i=0; i<D; ++i) {
            if ((dep[u] - dep[v]) >> i & 1) {
                u = rt[i][u];
            }
        }
        if (u == v) return u;
        for (int i=D-1; i>=0; --i)  {
            if (rt[i][u] != rt[i][v])   {
                u = rt[i][u];
                v = rt[i][v];
            }
        }
        return rt[0][u];
    }
    void solve(void)    {
        DFS (1, -1, 0);
        for (int i=1; i<D; ++i) {           //init_LCA
            for (int j=1; j<=n; ++j)    {
                rt[i][j] = rt[i-1][j] == -1 ? -1 : rt[i-1][rt[i-1][j]];
            }
        }
        int lca = LCA (u, v);
    }
    
    /*
        LCA -> RMQ: LCA (u, v) = F[id[u] <= i <= id[v]中dep[i]最小的i];
        RMQ预处理复杂度O(nlogn),每次询问O (1)
        (dp[N<<1][D], F[N<<1], dep[N<<1], id[N])
    */
    void DFS(int u, int fa, int d, int &k)  {
        id[u] = k;  F[k] = u;   dep[k++] = d;
        for (int i=head[u]; ~i; i=edge[i].nex)  {
            int v = edge[i].v;
            if (v == fa)    continue;
            DFS (v, u, d + 1, k);
            F[k] = u;   dep[k++] = d;
        }
    }
    int Min(int i, int j)   {
        return dep[i] < dep[j] ? i : j;
    }
    void init_RMQ(int k)  {
        for (int i=0; i<k; ++i)   dp[i][0] = i;
        for (int j=1; (1<<j)<=k; ++j) {
            for (int i=1; i+(1<<j)-1<k; ++i) {
                dp[i][j] = Min (dp[i][j-1], dp[i+(1<<(j-1))][j-1]);
            }
        }
    }
    int RMQ(int l, int r)   {
        int k = 0;  while (1<<(k+1) <= r - l + 1)   k++;
        return Min (dp[l][k], dp[r-(1<<k)+1][k]);
    }
    int LCA(int u, int v)   {
        u = id[u];  v = id[v];
        return u <= v ? F[RMQ (u, v)] : F[RMQ (v, u)];
    }
    
    /*
        LCA离线处理,Tarjan算法,复杂度O (N+Q)
        对询问次序按深搜时遍历到的节点顺序进行重组,并查集找祖先
        ans[i]表示第i个询问的LCA
    */
    void LCA(int u)    {
        rt[u] = u;
        for (int i=head[u]; ~i; i=edge[i].nex)  {
            int v = edge[i].v;
            if (rt[v] == -1)    {
                LCA (v);
                rt[v] = u;
            }
        }
        for (int i=headq[u]; ~i; i=query[i].nex)    {
            int v = query[i].v;
            if (rt[v] != -1)    {
                int lca = Find (v);
                ans[query[i].id] = lca;
            }
        }
    }
    

    推荐资源:Tarjan离线算法求LCA

    POJ 1330 Nearest Common Ancestors

    模版题

    /************************************************
    * Author        :Running_Time
    * Created Time  :2015/10/5 星期一 15:12:31
    * File Name     :POJ_1330.cpp
     ************************************************/
    
    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    #include <sstream>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <vector>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <list>
    #include <map>
    #include <set>
    #include <bitset>
    #include <cstdlib>
    #include <ctime>
    using namespace std;
    
    #define lson l, mid, rt << 1
    #define rson mid + 1, r, rt << 1 | 1
    typedef long long ll;
    const int N = 1e4 + 10;
    const int D = 20;
    const int INF = 0x3f3f3f3f;
    const int MOD = 1e9 + 7;
    const double EPS = 1e-8;
    struct Edge {
        int v, nex;
    }edge[N<<1];
    int head[N], in[N], e;
    int F[N<<1], dep[N<<1], id[N];
    int dp[N<<1][D];
    
    void init(void) {
        memset (head, -1, sizeof (head));
        memset (in, 0, sizeof (in));
        e = 0;
    }
    
    int Min(int i, int j)   {
        return dep[i] < dep[j] ? i : j;
    }
    
    void add_edge(int u, int v) {
        edge[e] = (Edge) {v, head[u]};
        head[u] = e++;
    }
    
    void DFS(int u, int fa, int d, int &k)  {
        id[u] = k;
        F[k] = u;
        dep[k++] = d;
        for (int i=head[u]; ~i; i=edge[i].nex)  {
            int v = edge[i].v;
            if (v == fa)    continue;
            DFS (v, u, d + 1, k);
            F[k] = u;
            dep[k++] = d;
        }
    }
    
    void init_RMQ(int k)  {
        memset (dp, 0, sizeof (dp));
        for (int i=0; i<k; ++i)   dp[i][0] = i;
        for (int j=1; (1<<j)<=k; ++j) {
            for (int i=1; i+(1<<j)-1<k; ++i) {
                dp[i][j] = Min (dp[i][j-1], dp[i+(1<<(j-1))][j-1]);
            }
        }
    }
    
    int RMQ(int l, int r)   {
        int k = 0;  while (1<<(k+1) <= r - l + 1)   k++;
        return Min (dp[l][k], dp[r-(1<<k)+1][k]);
    }
    
    int LCA(int u, int v)   {
        u = id[u];  v = id[v];
        return u <= v ? F[RMQ (u, v)] : F[RMQ (v, u)];
    }
    
    int main(void)    {
        int T;  scanf ("%d", &T);
        while (T--) {
            int n;  scanf ("%d", &n);
            init ();
            for (int u, v, i=1; i<n; ++i) {
                scanf ("%d%d", &u, &v);
                add_edge (u, v);    in[v]++;
            }
            int tot = 0;
            for (int i=1; i<=n; ++i)    {
                if (!in[i]) {
                    DFS (i, 0, 0, tot); break;
                }
            }
            init_RMQ (tot);
            int u, v;   scanf ("%d%d", &u, &v);
            printf ("%d
    ", LCA (u, v));
        }
    
        return 0;
    }
    

      

    HDOJ 2586 How far away ?

    模版题

    /************************************************
    * Author        :Running_Time
    * Created Time  :2015/10/4 星期日 18:36:06
    * File Name     :HDOJ_2586.cpp
     ************************************************/
    
    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    #include <sstream>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <vector>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <list>
    #include <map>
    #include <set>
    #include <bitset>
    #include <cstdlib>
    #include <ctime>
    using namespace std;
    
    #define lson l, mid, rt << 1
    #define rson mid + 1, r, rt << 1 | 1
    typedef long long ll;
    const int N = 4e4 + 10;
    const int M = 2e2 + 10;
    const int INF = 0x3f3f3f3f;
    const int MOD = 1e9 + 7;
    const double EPS = 1e-8;
    struct Edge {
        int v, nex, len;
    }edge[N*2];
    struct Query    {
        int v, nex, len, id;
    }query[M*2];
    int head[N], headq[N], rt[N], d[N], ans[M];
    int n, m, e, q;
    
    void init(void) {
        memset (head, -1, sizeof (head));
        memset (headq, -1, sizeof (headq));
        memset (rt, -1, sizeof (rt));
        e = 0;  q = 0;
    }
    
    void add_edge(int u, int v, int len) {
        edge[e].v = v;  edge[e].len = len;
        edge[e].nex = head[u];  head[u] = e++;
    }
    
    void add_query(int u, int v, int id) {
        query[q].v = v; query[q].id = id;
        query[q].nex = headq[u];    headq[u] = q++;
    }
    
    int Find(int x) {
        return rt[x] == x ? x : rt[x] = Find (rt[x]);
    }
    
    void LCA(int u, int len)    {
        d[u] = len; rt[u] = u;
        for (int i=head[u]; ~i; i=edge[i].nex)  {
            int v = edge[i].v;
            if (rt[v] == -1)    {
                LCA (v, len + edge[i].len);
                rt[v] = u;
            }
        }
        for (int i=headq[u]; ~i; i=query[i].nex)    {
            int v = query[i].v;
            if (rt[v] != -1)    {
                int lca = Find (v);
                ans[query[i].id] = d[u] + d[v] - (d[lca] << 1);
            }
        }
    }
    
    int main(void)    {
        int T;  scanf ("%d", &T);
        while (T--) {
            init ();
            scanf ("%d%d", &n, &m);
            for (int u, v, len, i=1; i<n; ++i)   {
                scanf ("%d%d%d", &u, &v, &len);
                add_edge (u, v, len);
                add_edge (v, u, len);
            }
            for (int u, v, i=1; i<=m; ++i)  {
                scanf ("%d%d", &u, &v);
                add_query (u, v, i);
                add_query (v, u, i);
            }
            LCA (1, 0);
            for (int i=1; i<=m; ++i)    {
                printf ("%d
    ", ans[i]);
            }
        }
    
        return 0;
    }
    

     

    编译人生,运行世界!
  • 相关阅读:
    九度-题目1197:奇偶校验
    九度-题目1073:杨辉三角形
    九度-题目1072:有多少不同的面值组合?
    同步异步,阻塞非阻塞
    注解方式配置bean
    监听器
    自定义系统初始化器
    构建流
    数值流
    流的使用
  • 原文地址:https://www.cnblogs.com/Running-Time/p/4857311.html
Copyright © 2020-2023  润新知