首页 > 其他分享 >割点

割点

时间:2024-09-26 09:37:23浏览次数:1  
标签:int 割点 dfn low 追溯 节点

割点(Articulation Point)

在图论中,割点(Articulation Point)是指在一个无向图中,如果删除某个节点及其关联的边会导致图的连通分量数量增加,那么这个节点就被称为割点。换句话说,割点是图中的一个节点,删除它会使图变得不连通或减少连通分量的数量。

性质

  1. 连通性:删除割点会使得图的连通性降低,即原本连通的节点变得不连通。
  2. 无向图:割点的概念主要应用于无向图。
  3. 割点的检测:可以使用Tarjan算法来检测图中的割点。

Tarjan算法检测割点

Tarjan算法是一种深度优先搜索(DFS)算法,用于检测图中的割点和强连通分量。以下是Tarjan算法检测割点的基本步骤:

  1. 初始化

    • 为每个节点设置一个时间戳(dfn)和一个追溯值(low)。
    • 使用一个栈来记录访问的节点。
  2. DFS遍历

    • 从任意一个节点开始进行DFS遍历。
    • 对于每个节点,记录其访问时间戳(dfn)和追溯值(low)。
    • 对于每个节点的邻接节点,如果邻接节点未被访问过,则递归访问,并更新当前节点的追溯值(low)。
    • 如果邻接节点的追溯值(low)大于等于当前节点的时间戳(dfn),则当前节点是割点。
  3. 割点判定

    • 如果 low[v] >= dfn[u],则节点 u 是割点。

代码:

题目

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N = 2e5 + 10, mod = 998244353;
typedef long long ll;
typedef pair<int, int> PII;

int T;
int dfn[N], low[N], n, m, idx; // dfn: 时间戳, low: 追溯值, n: 节点数, m: 边数, idx: 时间戳计数器
vector<int> g[N]; // 图的邻接表表示
int cut[N]; // 记录节点是否为割点
int ans = 0; // 割点的数量

// Tarjan算法检测割点
void Tarjan(int u, int p) {
    dfn[u] = low[u] = ++idx; // 初始化时间戳和追溯值
    int sz = 0; // 记录子树的数量
    for (auto v : g[u]) {
        if (!dfn[v]) { // 如果节点v未访问过
            Tarjan(v, u); // 递归访问v
            sz++; // 子树数量加1
            low[u] = min(low[u], low[v]); // 更新追溯值
            if (low[v] >= dfn[u]) cut[u] = 1; // 如果v的追溯值大于等于u的时间戳,则u是割点
        } else if (v != p) { // 如果v不是父节点
            low[u] = min(low[u], dfn[v]); // 更新追溯值
        }
    }
    if (p == 0 && sz <= 1) cut[u] = 0; // 如果u是根节点且子树数量小于等于1,则u不是割点
    ans += cut[u]; // 更新割点数量
}

signed main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n >> m; // 读取节点数和边数
    for (int i = 1; i <= m; i++) {
        int u, v;
        cin >> u >> v; // 读取边
        g[u].push_back(v); // 添加边到邻接表
        g[v].push_back(u); // 无向图,双向添加
    }
    for (int i = 1; i <= n; i++) {
        if (!dfn[i]) Tarjan(i, 0); // 对每个未访问的节点运行Tarjan算法
    }
    cout << ans << endl; // 输出割点的数量
    for (int i = 1; i <= n; i++) {
        if (cut[i]) cout << i << " "; // 输出所有割点
    }
    return 0;
}

标签:int,割点,dfn,low,追溯,节点
From: https://www.cnblogs.com/Violetfan/p/18432778

相关文章

  • Tarjan 之 割点 学习笔记
    首先,要求割点,我们需要知道割点是什么割点:是指在无向连通图中,如果删除某个顶点后,图的连通分量增加,则称该顶点为割点好,知道了这个,那我们怎么去求他呢?Tarjan大神给出了一种依然基于时间戳的算法图片来源:董晓算法割点的求法大概就是这样的所以细节还是见代码吧#include<bit......
  • 割点 and 割边
    P3388【模板】割点Note:图可能不联通,因此每次tarjan都要更新root#include<cstdio>#include<stack>#include<cmath>#include<algorithm>#include<iostream>#include<cstring>#include<vector>#defineintlonglong#defineiosstd......
  • 无向图的连通性(割点与割边)
    割点与割边 割点的求解方法  割点详解 板题:https://www.luogu.com.cn/problem/P3388  第1题   割点 查看测评数据信息给出一个n个点,m条边的无向图,求图的割点。输入格式 第一行输入两个正整数n,m。下面m行每行输入两个正整数x,y表示x到y有一......
  • C++的算法:割点与割边
            在图论中,割点与割边是图的重要性质,它们在图的连通性、网络流等问题中扮演着关键角色。在C++中,我们可以通过深度优先搜索(DFS)等算法来判定一个图中的割点与割边。        割点,又称关节点或桥接点,是指在无向连通图中,如果删除某个顶点后,图的连通分量数增......
  • 【图论】割点(割顶)
    前置定义有无向图\(G=(V,E).\)无向图的DFS树:从某一点\(root\)开始DFS,访问邻点\(.\)当搜索到点\(u\)时,我们遍历每一条以\(u\)为起点的边\((u,v_i)\),且定义有向边\(u\longrightarrowv_i.\)于是DFS的过程全部完成之后,所有被定义的有向边就会组成一颗以\(r......
  • 图论-割点与点双连通分量
    首先是两篇的代码割点点击查看代码inthead[N],cnt=0;structEdge{intfrom,to,nxt;}e[N<<1];voidadd(intu,intv){e[++cnt].from=u;e[cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;}intdfn[N],back[N],tim;//dfn[i]时......
  • 图论-割点与割边
    这是摘自算法书上的一篇Tarjan求割点算法dfn[i]代表时间戳数组back[i]代表该点不依靠祖先节点能回到的最远的祖先节点采用链式前向星建图,结果存储在iscut[]数组中点击查看代码inthead[N],cnt=0;structEdge{intfrom,to,nxt;}e[N<<1];voidadd(......
  • 桥、割点和边双连通分量
    桥定义:删除后会增加联通块数量的边被称作桥。那么,如何求解呢?方法一首先跑出一颗dfs树。比如下图(\(2-6,1-5\)的边是非树边):可以发现,所有非树边和其构成的环上的所有边不可能是桥,因为删去后仍可以通过环的另一半。比如上图中只有\(1-2\)一个桥。那是不是除了这些边以外都是......
  • 割点
    割点割点是如果删除这个点,连通块+1的点就是割点。可以发现,在DFS树上,如果一个点的儿子不能通过一些非树边到达它的父亲,如果把它删除,这个儿子将会和他的父亲不连通。#include<bits/stdc++.h>usingnamespacestd;constintN=2e5+5;intlow[N],cnt,dfn[N......
  • 图论割点模板
    #include<iostream>#include<vector>#include<algorithm>#include<math.h>#include<sstream>#include<string>#include<string.h>#include<iomanip>#include<stdlib.h>#include<map>#include<queue......