首页 > 其他分享 >tarjan

tarjan

时间:2023-08-27 13:11:07浏览次数:43  
标签:tarjan int 割点 dfn low 节点

割点与桥

简介

割点:对于一个无向图,如果把一个点及与其相连的边删除后这个图分裂为两个及两个以上不连通的子图,那么这个点就是这个图的割点(又称割顶)。

割边:对于一个无向图,如果把一条边删除后这个图分裂为两个不连通的子图,那么这个点就是这个图的割边(又称桥)。

tarjan 求割点

定理:如果 \(x\) 为割点,那么在 \(x\) 的子节点只能通过 \(x\) 到达 \(x\) 的祖先节点。

证明:设 \(y\) 为 \(x\) 的子节点,\(z\) 为 \(x\) 的父节点,且有边 \(y→z\) 。
若去掉边 \(x→y\),图仍然连通,故 \(x\) 不是割点,与原条件矛盾,因此假设不成立。

image

可以发现,如果一个节点不经过其父节点能到达的最小的时间戳如果大于其父节点的时间戳,那么它就满足只能通过其父节点到达其父节点的祖先节点。也就是说,它的父节点是割点
这就是 tarjan 算法求割点的核心原理。

tarjan 求割点的流程:

  1. 求出每个节点时间戳 \(dfn_i\)(dfs 序)。

  2. 访问节点 \(x\)。

    1. 遍历 \(x\) 的每个子节点 \(y\)。
    2. 求出每个节点 \(y\) 不经过其父亲能到达的最小的时间戳,记为 \(low_y\)。
      • \(y\) 没被访问过
        先处理以 \(y\) 为起点的子图。
        更新 \(low_x\),显然有 \(low_x=\min(low_x,low_y)\)。
        如果 \(x\) 不是连通块的起始节点并且 \(low_x\ge dfn_y\),\(x\) 是一个割点。
      • \(y\) 被访问过
        有 \(low_x=\min(low_x,dfn_y)\)。
    3. 如果 \(x\) 是当前连通块的起点并且与两个以上的节点相连,\(x\) 是一个割点。

代码

#include <bits/stdc++.h>
using namespace std;
int n, m, t, idx, cnt, v[1000005], h[1000005], ne[1000005], dfn[1000005], low[1000005];
bool vis[1000005], flag[1000005];
inline void add(int a, int b) {
    v[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
inline void tarjan(int x, int F) {
    vis[x] = 1;
    low[x] = dfn[x] = ++t;
    int child = 0;

    for (int i = h[x]; ~i; i = ne[i]) {
        int y = v[i];

        if (!vis[y]) {
            tarjan(y, x);
            low[x] = min(low[x], low[y]);

            if (!flag[x] && F != x && low[y] >= dfn[x])
                flag[x] = 1, cnt++;

            child++;
        } else if (y != F)
            low[x] = min(low[x], dfn[y]);
    }

    if (!flag[x] && x == F && child >= 2)
        flag[x] = 1, cnt++;
}
int main() {
    memset(h, -1, sizeof h);
    cin >> n >> m;

    while (m--) {
        int x, y;
        cin >> x >> y;
        add(x, y), add(y, x);
    }

    for (int i = 1; i <= n; i++) {
        if (vis[i])
            continue;

        t = 0, tarjan(i, i);
    }

    cout << cnt << '\n';

    for (int i = 1; i <= n; i++)
        if (flag[i])
            cout << i << ' ';

    return 0;
}

标签:tarjan,int,割点,dfn,low,节点
From: https://www.cnblogs.com/wangxuzhou-blog/p/tarjan.html

相关文章

  • Tarjan基础用法
    \(\operatorname{Tarjan}\)基础用法目录\(\operatorname{Tarjan}\)基础用法\(\operatorname{Tarjan}\)求最近公共祖先前置芝士实现过程例题\(\operatorname{Tarjan}\)求割点、割边前置芝士\(\operatorname{Tarjan}\)求割点\(\operatorname{Tarjan}\)求割边例题\(\operatorn......
  • [Tarjan] 学习笔记
    原理强连通分量讲得超级屌,这次比董晓好得多voidtarjan(intx){ dfn[x]=low[x]=t++; s.push(x); in[x]=true; for(inti=h[x];i;i=e[i].next) { inty=e[i].to; if(!dfn[y]) { tarjan(y); low[x]=min(low[x],low[y]); } elseif(i......
  • Tarjan学习笔记
    TarjanTarjan算法是图论中非常常用的算法之一,能解决强连通分量,双连通分量,割点和桥,求最近公共祖先(LCA)等问题。Tarjan算法是基于深度优先搜索的算法,用于求解图的连通性问题。割点如果从图中删除节点\(x\)以及所有与\(x\)关联的边之后,图将被分成两个或两个以上的不相连的......
  • 强连通分量与tarjan算法
    强连通分量强连通:若一张有向图的节点两两之间可以互相抵达,那么这一张图是强连通的。强连通分量:极大的强连通子图。对图深度搜索的时候,每一个节点只访问一次,被访问过的节点与边构成搜索树。有向边按照访问的情况可以分为如下4类:1.树边:访问节点走过的边。2.返祖边:指向祖......
  • 【W的AC企划 - 第八期】tarjan缩点
    往期浏览第一期-博弈论(game)第二期-前缀和第三期-二分算法第四期-莫队算法第五期-线段树第六期-位运算(Bitmasks)第七期-树上分治第八期-Tarjan缩点第九期(拟)-树上启发式合并讲解(有向图)强连通分量缩点概念强连通分量缩点后的图称为SCC。有两种......
  • tarjan模板
    ilvoidtarjan(intu){ dfn[u]=low[u]=++num,st[++top]=u,ins[u]=1; G(i,u) { intv=ver[i]; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } elseif(ins[v])low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]) { intt=0; cnt++; do......
  • Tarjan 例题:洛谷P1407 [国家集训队] 稳定婚姻
    在洛谷中查看题意:自己读一下,大致就是\(2n\)个点,每个点编号为\(1-2n\),\(\lfloor编号/2\rfloor\)相同的点连条边。然后再给\(m\)条边。问:将每个\(\lfloor编号/2\rfloor\)相同的点间连的边断开,还能不能使每个编号为奇数的点都有一个编号为偶数的点对应。这个......
  • Tarjan
    我写这个随笔是让我更加理解算法,防止以后出错,因为我今天调Tarjan调了3个多小时,后来还是在大佬的帮忙下调出来了,问题不少先来看错误的(40pts): //缩点//https://www.luogu.com.cn/problem/P3387#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;con......
  • tarjan,点双和边双学习笔记。
    发现之前学的真的一塌糊涂呢(/ω\)很多非常精髓的地方理解的都不够好,比如说为啥我要用一棵dfs树来为框架,跑tarjan?这里我就理解的不好,所以我来重新写一篇,加深加深印象。以下一切默认为无向图。0.基本概念这里面说的非常不严谨,只是为了方便理解啦awa连通分量:你可以简单的......
  • Tarjan缩点
    P3225[HNOI2012]矿场搭建一共只会删除一个点,将每个点双连通分量分三种情况讨论第一种:点双连通分量没有割点,那么为了保证一定可以逃出去,至少需要两个点第二种:点双连通分量有且只有一个割点,此处割点是绿色的点,那么对于这种点双连通分量就需要在每个只有一个割点的双连通分量......