【LCA】Tarjan离线算法(并查集+dfs)模板

vector <int> Q[N];

int Find(int x)
{
    if(x != fa[x]) return fa[x] = Find(fa[x]);
    return x;
}

void Union(int x, int y)
{
    int fx = Find(x), fy = Find(y);
    if(fy != fx) fa[fy] = fx;
}

void dfs(int u)
{
    anc[u] = u;
    for(int i = head[u]; ~i; i = e[i].next) {
        int v = e[i].v;
        dfs(v);
        Union(u, v);
        anc[Find(u)] = u;
    }
    vis[u] = true;
    int sz = Q[u].size();
    for(int i = 0; i < sz; i++) {
        int v = Q[u][i];
        if(vis[v]) {
            printf("%d\n", anc[Find(v)]);
            return ;
        }
    }
}
时间: 2024-10-06 22:43:06

【LCA】Tarjan离线算法(并查集+dfs)模板的相关文章

【C++】最近公共祖先LCA(Tarjan离线算法)&amp;&amp; 洛谷P3379LCA模板

1.前言 首先我们介绍的算法是LCA问题中的离线算法-Tarjan算法,该算法采用DFS+并查集,再看此算法之前首先你得知道并查集(尽管我相信你如果知道这个的话肯定是知道并查集的),Tarjan算法的优点在于相对稳定,时间复杂度也比较居中,也很容易理解(个人认为). 2.思想 下面详细介绍一下Tarjan算法的思想: 1.任选一个点为根节点,从根节点开始. 2.遍历该点u所有子节点v,并标记这些子节点v已被访问过. 3.若是v还有子节点,返回2,否则下一步. 4.合并v到u上. 5.寻找与当前点

POJ 1330 Nearest Common ancesters(LCA,Tarjan离线算法)

Description: In the figure, each node is labeled with an integer from {1, 2,...,16}. Node 8 is the root of the tree. Node x is an ancestor of node y if node x is in the path between the root and node y. For example, node 4 is an ancestor of node 16.

LCA(最近公共祖先)--tarjan离线算法 hdu 2586

HDU 2586 How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 11320    Accepted Submission(s): 4119 Problem Description There are n houses in the village and some bidirectional roads c

笔记: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

HDU 2586 How Far Away?(Tarjan离线算法求lca)

题意:给定一棵树n个节点m个询问,每次询问两个节点之间的距离. 思路:Tarjan离线算法求lca. 这题一开始交了n发一直爆栈.......百度了一下大概说的是这样hdu用的是windows服务器所以栈大小极其坑爹,稍微深一点的递归就会爆栈(正式比赛一般不会爆) 解决方法就是加一句#pragma comment(linker, "/STACK:1024000000,1024000000") 用c++交就好.....当然这只是针对比较坑爹oj来说的取巧的方法 #include<c

【bzoj4551】[Tjoi2016&amp;Heoi2016]树 离线处理+并查集

题目描述 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为1),有以下两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均无标记,而且对于某个结点,可以打多次标记.)2. 询问操作:询问某个结点最近的一个打了标记的祖先(这个结点本身也算自己的祖先)你能帮帮他吗? 输入 输入第一行两个正整数N和Q分别表示节点个数和操作次数接下来N-1行,每行两个正整数u,v(1≤u,v≤n)表示u到v有一条有向边接下来Q行,形如"oper

BZOJ 3562: [SHOI2014]神奇化合物 并查集+dfs

点击打开链接 注意到20w条边,但是询问只有1w,所以有很多边是从头到尾不变的. 首先离线处理,将从未删除的边缩点,缩点后的图的点数不会超过2w,对于每一次add或者delete,直接dfs看是否能从a走到b,然后维护一个ans. 数据不强,不然这种复杂度起码要跑10s.. #include<stdio.h> #include<iostream> #include<algorithm> #include<cstring> using namespace st

URAL1671 Anansi&#39;s Cobweb(离线做 + 并查集)

传送门 大意:给出一个无向图,删除Q条边,每删除一次就询问一次目前的连通块的数目. 思路:离线搞, 把删边转换为加边,每加一次边,若两个顶点不连通就用并查集把着这两个连通块合并. 代码: #include<cstdio> #include<cstring> #include<algorithm> #define MAXN 100005 using namespace std; int n, m, q; int s[MAXN], t[MAXN]; int ban[MAXN

Codeforces 455C Civilization(并查集+dfs)

题目链接:Codeforces 455C Civilization 题目大意:给定N,M和Q,N表示有N个城市,M条已经修好的路,修好的路是不能改变的,然后是Q次操作,操作分为两种,一种是查询城市x所在的联通集合中,最长的路为多长.二是连接两个联通集合,采用联通之后最长路最短的方案. 解题思路:因为一开时的图是不可以改变的,所以一开始用dfs处理出各个联通集合,并且记录住最大值,然后就是Q次操作,用并查集维护,注意因为联通的时候要采用最长路径最短的方案,所以s的转移方程变为s = max(s,

【bzoj5183】[Baltic2016]Park 离线+对偶图+并查集

题目描述 在Byteland的首都,有一个矩形围栏围起来的公园.在这个公园里树和访客都以一个圆形表示.公园有四个出入口,每个角落一个(1=左下角,2=右下角,3=右上角,4=左上角).访客能通过这些出入口进出公园.访客在同时碰到一个角落的两条边时就可以通过该角落进出公园.访客在公园里可以自由地移动,但他们不能和树和围栏相交.对于每个访客,给定他们进入公园的出入口,你的任务是计算他们能在哪个出入口离开公园. 输入 输入的第一行包含两个整数:n,m:树的数量和访客的数量. 第二行包含两个整数:w,h