美文网首页
Tarjan算法求割点和桥

Tarjan算法求割点和桥

作者: 学无止境1980 | 来源:发表于2019-02-19 20:37 被阅读5次

定义:

  • 割点:在一个无向连通图中,若删除某点后,图变成不连通,则称该点为该图的割点。
  • 桥:在一个无向连通图中,若删除某边后,图变成不连通,则称该边为该图的桥。

Tarjan算法求割点和桥的思路同样也基于对图的DFS:

  • dfn[u]表示u节点在DFS搜索中是第几个被搜索到的(时间戳)。
  • low[u]表示从在DFS搜索树中以u节点为根的子树中节点不通过u节点的父节点到u节点这条边所能到达的所有节点的dfn的最小值。

一个节点u是割点,当且仅当满足下面的条件1或2:

  1. 如果节点u是总的DFS树的根,该节点u有多于1个的子树。
  2. 如果节点u不是总的DFS树的根,该节点u存在一颗子树,子树的根节点为v,且dfn[u]\leq low[v]

一条边(u,v)是桥,当且仅当边(u,v)没有重边,且dfn[u]<low[v]

需要使用到的全局变量的定义:

int N; // N表示节点总个数
vector <int> E, cutp; // cutp存储割点
int dfn[MAXN], low[MAXN], timer;
struct Edge{int from, to;};
vector <Edge> br; // br存储桥

DFS搜索可以如下实现(参考代码):

// 这段代码求桥时未考虑重边的情况
void dfs(int u, int fa){
    dfn[u] = low[u] = ++timer;
    int son = 0;
    bool f = false;
    for(int i=0;i<E[u].size();i++){
        int v = E[u][i];
        if(v == fa) continue;
        if(!dfn[v]){
            son++;
            dfs(v, u);
            if(dfn[u] <= low[v]) f = true;
            if(dfn[u] < low[v]) br.push_back((Edge){u, v});
            low[u] = min(low[u], low[v]);
        }
        else low[u] = min(low[u], dfn[v]);
    }
    if((!fa && son>1) || (fa && f)) cutp.push_back(u);
}

Tarjan算法只需要调用上面的dfs函数即可,代码如下:

void Tarjan(){
    for(int i=1;i<=N;i++){
        if(!dfn[i]) dfs(i, 0);
    }
}

附上一道练习题,链接洛谷P3388 【模板】割点(割顶)

AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <stack>
using namespace std;
const int MAXN = 20000+10;
int N, M;
vector <int> E[MAXN], cutp;
int dfn[MAXN], low[MAXN], timer;
void dfs(int u, int fa){
    dfn[u] = low[u] = ++timer;
    int son = 0;
    bool f = false;
    for(int i=0;i<E[u].size();i++){
        int v = E[u][i];
        if(v == fa) continue;
        if(!dfn[v]){
            son++;
            dfs(v, u);
            if(dfn[u] <= low[v]) f = true;
            low[u] = min(low[u], low[v]);
        }
        else low[u] = min(low[u], dfn[v]);
    }
    if((!fa && son>1) || (fa && f)) cutp.push_back(u);
}
void Tarjan(){
    for(int i=1;i<=N;i++){
        if(!dfn[i]) dfs(i, 0);
    }
}
int main(){
    scanf("%d%d", &N, &M);
    while(M--){
        int from, to;
        scanf("%d%d", &from, &to);
        E[from].push_back(to);
        E[to].push_back(from);
    }
    Tarjan();
    printf("%d\n", (int)cutp.size());
    sort(cutp.begin(), cutp.end());
    for(int i=0;i<cutp.size();i++)
        printf(i<cutp.size()-1?"%d ":"%d\n", cutp[i]);
    return 0;
}

相关文章

  • Tarjan算法求割点和桥

    定义: 割点:在一个无向连通图中,若删除某点后,图变成不连通,则称该点为该图的割点。 桥:在一个无向连通图中,若删...

  • Tarjan算法求割点,桥

    下面介绍中无向图中割点和桥的概念:割点:一个结点称为割点(或者割顶)当且仅当去掉该节点极其相关的边之后的子图不连通...

  • 连通图

    Strongly Connected Componenet 割点(tarjan): 题目链接:Network(求割...

  • 无向图求割点和割边——Tarjan算法

    无向图中求割点集和割边集——Tarjan算法割点和割边定义在一个无向图中,如果删除了某个顶点及与之相连的所有边,产...

  • 图论-----求割点

    求无向连通图割点(java)-------Tarjan算法 在无向连通图中,如果将其中一个点以及所有连接该点的边去...

  • 图论(1)-tarjan算法求强联通分量,割点,桥

    在LC里面的图论题,一般还是非常基础的,BFS,或者Dijkstra 为主。造成其实有很多经典的图论算法运用的不多...

  • 图的桥和割点

    内容概要: 图中的桥 图的DFS遍历树和BFS遍历树及其与寻桥算法的关系 图的割点 DFS和BFS的对比小结 桥(...

  • tarjan-LCA最近公共祖先离线算法

    在一棵树上查询任意两个点的最近公共祖先,或求最短距离的离线算法tarjan,基于dfs遍历和并查集,在查询时倍增直...

  • tarjan算法

    tarjan算法前提 一个关于图的联通性的神奇算法。基于DFS(深度搜索)算法,深度优先搜索一张有向图。!注意!是...

  • 图论(八)桥(割边)和割点

    一、桥 1.1 定义 对于无向图,如果删除了一条边,整个图的联通分量数量变化,则这条边称为桥如图,红色标注的线就是...

网友评论

      本文标题:Tarjan算法求割点和桥

      本文链接:https://www.haomeiwen.com/subject/xrifyqtx.html