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\n",ans[findset(T)]);
            return;
        }
    }
    else
    if (u==T){
        if (vis[S]){
            printf("%d\n",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;
}

  

POJ 1330 LCA最近公共祖先 离线tarjan算法

时间: 2024-08-27 22:59:35

POJ 1330 LCA最近公共祖先 离线tarjan算法的相关文章

poj 1330 LCA 最近公共祖先

水题目.直接上代码了. VIEW CODE #include<cstdio> #include<algorithm> #include<iostream> #include<cmath> #include<queue> #include<stack> #include<string> #include<cstring> #include<map> #include<vector> #in

POJ - 1470 Closest Common Ancestors(离线Tarjan算法)

1.输出测试用例中是最近公共祖先的节点,以及这个节点作为最近公共祖先的次数. 2.最近公共祖先,离线Tarjan算法 3. /* POJ 1470 给出一颗有向树,Q个查询 输出查询结果中每个点出现次数 */ /* 离线算法,LCATarjan 复杂度O(n+Q); */ #include<iostream> #include<stdio.h> #include<string.h> using namespace std; const int MAXN=1010; co

poj 1330 【最近公共祖先问题+fa[]数组+ 节点层次搜索标记】

题目地址: 节点编号为:1-->n 代码: #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #include <math.h> #include <iostream> #include <queue> #include <stack> #include <vector> #include

【算法】树上公共祖先的Tarjan算法

最近公共祖先问题 树上两点的最近公共祖先问题(LCA - Least Common Ancestors) 对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u和v的祖先且x的深度尽可能大.在这里,一个节点也可以是它自己的祖先. 例如,如图,在以A为根的树上 节点 8 和 9 的LCA为 4 节点 8 和 5 的LCA为 2 节点 8 和 3 的LCA为 1 在线算法与离线算法 区别就在于是同时处理询问后输出还是边询问边输出 在线算法是读入一组询问,查询一次后紧

hicocoder1067 最近公共祖先&#183;二(tarjan算法)

tarjan算法是处理最近公共祖先问题的一种离线算法. 算法思路: 先将所有的询问搜集起来. 然后对树进行dfs,在dfs的过程中对节点进行着色.当到达某个节点x的时候,给x着色为灰色,离开x的时候,着色为黑色. 当到达x并将其着色为灰色后,处理与x相关联的所有询问: (这里有一个显然的事实:所有的灰色节点都是x的祖先) (1)若询问的另一个节点y是灰色,那么该询问的结果为y: (2)若询问的另一个节点y是黑色,那么询问结果应为离y最近的y的灰色祖先(因为所有灰色节点都是x的祖先,所以离y最近的

[HDOJ2586]How far away?(最近公共祖先, 离线tarjan, 并查集)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 这题以前做过…现在用tarjan搞一发…竟然比以前暴力过的慢………… 由于是离线算法,需要Query来保存查询数据,Ans来保存结果.最后输出的时候按照idx的顺序输出,所以胡搞了个排序.. dfs每次更新depth,当前点depth是上一个点累积下来的. 1 /* 2 ━━━━━┒ギリギリ♂ eye! 3 ┓┏┓┏┓┃キリキリ♂ mind! 4 ┛┗┛┗┛┃\○/ 5 ┓┏┓┏┓┃ / 6

[笔记]LCA最近公共祖先---倍增在线算法

059M37853N虏3Jhttp://www.zcool.com.cn/collection/ZMTg2OTM5ODg=.html 痹o83RI世9EUS两http://www.zcool.com.cn/collection/ZMTg2OTQwMTY=.html 猩骋05K型51抡MChttp://www.zcool.com.cn/collection/ZMTg2OTQxMjg=.html 4辣腾膛且j匠9坝3凳W1http://www.zcool.com.cn/collection/ZMTg

笔记:LCA最近公共祖先 Tarjan(离线)算法

LCA最近公共祖先 Tarjan他贱(离线)算法的基本思路及其算法实现 本文是网络资料整理或部分转载或部分原创,参考文章如下: https://www.cnblogs.com/JVxie/p/4854719.html http://blog.csdn.net/ywcpig/article/details/52336496 https://baike.baidu.com/item/最近公共祖先/8918834?fr=aladdin 最近公共祖先简称LCA(Lowest Common Ancesto

lca 最近公共祖先

http://poj.org/problem?id=1330 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define mt(a,b) memset(a,b,sizeof(a)) 5 using namespace std; 6 const int inf=0x3f3f3f3f; 7 class LCA { ///最近公共祖先 build_o(n*logn) query_o(1) 8 t