zoukankan      html  css  js  c++  java
  • 图论LCA

    离线Tarjan

    算法思想

    离线处理,先记录需要找的点

    链式前向星模板

    #include <bits/stdc++.h>
    using namespace std;
    #define mem(a,b) memset(a,b,sizeof(a))
    #define cin(a) scanf("%d",&a)
    #define pii pair<int,int>
    #define ll long long
    #define gcd __gcd
    const int inf = 0x3f3f3f3f;
    const int maxn = 1000100;
    const int M = 1e9+7;
    int n,m,s,cnt;
    
    int head[maxn],to[maxn],Next[maxn];        //链式前向星
    vector<pii> q[maxn];           //询问
    int pre[maxn];                 //先驱
    bool vis[maxn];                //是否访问过
    int ans[maxn];                 //记录第i个询问的答案
    
    void add(int u,int v)
    {
        to[cnt] = v;Next[cnt] = head[u]; head[u] = cnt;
        cnt++;
    }
    
    int find(int x)
    {
        return x == pre[x] ? x : pre[x] = find(pre[x]);
    }
    
    void dfs(int u,int from)
    {
        for(int i = head[u]; i != -1; i = Next[i])
        {   
            int v = to[i];
            if(v != from)
            {
                dfs(v,u);
                pre[v] = u;
            }
        }
        for(auto j : q[u])
        {
            if(vis[j.first])
            {
                ans[j.second] = find(j.first);
            }
        }
        vis[u] = 1;
    }
    
    int main()
    {
    #ifdef ONLINE_JUDGE
    #else
        freopen("data.in", "r", stdin);
        //freopen("data.out", "w", stdout);
    #endif
        scanf("%d%d%d",&n,&m,&s);
        for(int i = 1; i <= n; i++) head[i] = -1,pre[i] = i;
        for(int i = 1,u,v; i < n; i++)
        {
            scanf("%d%d",&u,&v);
            add(u,v);add(v,u);
        }
        for(int i = 1,u,v; i <= m; i++)
        {
            scanf("%d%d",&u,&v);
            q[u].push_back(make_pair(v,i));
            q[v].push_back(make_pair(u,i));
        }
        dfs(s,0);
        for(int i = 1; i <= n; i++) printf("%d\n",ans[i]);
        return 0;
    }
    

    倍增LCA

    预处理过程:O(nlogn)
    先用dfs或者bfs求出每个点的deep,然后更新每个点的fa数组
    查询过程:O(logn)
    1.假设x的深度更小(在y的上面)
    2.y开始向上跳,跳到和x同深度
    3.x,y一起向上跳

    int d[maxn];      //深度
    int fa[maxn][20];     //节点i的2^i级祖先
    
    void dfs(int u,int pre)
    {
        d[u] = d[pre]+1;
        fa[u][0] = pre;
        for(int i = 1; (1<<i) <= d[u]; i++)
        {
            fa[u][i] = fa[fa[u][i-1]][i-1];
        }
        for(int i = head[u]; i ; i = Next[i])
        {   
            int v = to[i];
            if(v != pre)
            {
                dfs(v,u);
            }
        }
    }
    
    //t = log(n)/log(2)+1; 可能的最大深度
    
    int lca(int x,int y)
    {
        if(d[x] > d[y]) swap(x,y);      //让x的深度更小
        for(int i = t; i >= 0; i--)     //首先y要跳到和x深度相同
        {
            if(d[fa[y][i]] >= d[x]) y = fa[y][i];       //如果y^i还是在x下面,跳到y^i
        }
        //此时,x和y的深度一定相等
        if(x == y) return x;            //如果就是x,return
        for(int i = t; i >= 0; i--)     //从打的开始
        {
            if(fa[x][i] != fa[y][i])    //如果x的第i层和y的第i层不相同,如果相同说明跳过头了
            {
                x = fa[x][i];y=fa[y][i];
            }
        }
        return fa[x][0];                //此时的x的父节点一定是lca
    }
    

    参考博客

    https://www.cnblogs.com/JVxie/p/4854719.html
    https://www.cnblogs.com/hulean/p/11144059.html
    https://blog.csdn.net/zhaoxinxin1234/article/details/89764483

  • 相关阅读:
    Orient DB 0.9.6 Beta 发布下载
    Java 近些年一直群龙无首 Google 为 Java 前途担忧
    VC和LUA混合开发之VC程序调用Lua脚本函数
    NetBeans 时事通讯(刊号 # 99 Apr 16, 2010)
    Cassandra 0.6 发布下载
    JDK 6 Update 20 发布下载JDK 6最新版本下载
    Java 近些年一直群龙无首 Google 为 Java 前途担忧
    Simple way to export SQL Server data to Text Files
    GFORTRAN
    The Stanford NLP (Natural Language Processing) Group
  • 原文地址:https://www.cnblogs.com/hezongdnf/p/12018599.html
Copyright © 2011-2022 走看看