zoukankan      html  css  js  c++  java
  • POJ 1330 LCA最近公共祖先 离线tarjan算法

    题意要求一棵树上,两个点的最近公共祖先 即LCA

    现学了一下LCA-Tarjan算法,还挺好理解的,这是个离线的算法,先把询问存贮起来,在一遍dfs过程中,找到了对应的询问点,即可输出

    原理用了并查集和dfs染色,先dfs到底层开始往上回溯,边并查集合并 一边染色,这样只要询问的两个点均被染色了,就可以输出当前并查集的最高父亲一定是LCA,因为我是从底层层层往上DSU和染色的,要么没被染色,被染色之后,肯定就是当前节点是最近的

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    using namespace std;
    const int N = 10000+10;
    int f[N],pre[N],vis[N];
    int ans[N];
    vector<int> v[N];
    int n,S,T;
    void init()
    {
        for (int i=0;i<=n+1;i++){
            f[i]=i;
            v[i].clear();
            vis[i]=0;
            pre[i]=-1;
        }
    }
    int findset(int x)
    {
        if (x!=f[x]){
            f[x]=findset(f[x]);
        }
        return f[x];
    }
    int unionset(int a,int b)
    {
        int r1=findset(a);
        int r2=findset(b);
        if (r1==r2) return r1;
        f[r2]=r1;
        return r1;
    }
    void LCA(int u)
    {
        ans[u]=u;
    
        for (int i=0;i<v[u].size();i++){
            int vx=v[u][i];
            LCA(vx);
            int rt=unionset(u,vx);
            ans[rt]=u;
        }
        vis[u]=1;
        if (u==S){
            if (vis[T]){
                printf("%d
    ",ans[findset(T)]);
                return;
            }
        }
        else
        if (u==T){
            if (vis[S]){
                printf("%d
    ",ans[findset(S)]);
                return;
            }
        }
    
    }
    int main()
    {
        int t,a,b;
        scanf("%d",&t);
        while (t--){
          scanf("%d",&n);
          init();
          for (int i=1;i<n;i++){
              scanf("%d%d",&a,&b);
              v[a].push_back(b);
              pre[b]=a;
          }
          scanf("%d%d",&S,&T);
          for (int i=1;i<=n;i++){
              if (pre[i]==-1){
                  LCA(i);
                  break;
              }
          }
        }
        return 0;
    }
    

      

  • 相关阅读:
    springMVC源码分析
    世界近代史二
    世界近代历史
    UVA
    UVA
    UVA
    Web 前端开发学习之路(入门篇)
    01 Linux入门介绍
    2. Python基本知识
    1. 初识Python
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3902868.html
Copyright © 2011-2022 走看看