首页 > 其他分享 >【图论】割点(割顶)

【图论】割点(割顶)

时间:2024-05-26 12:44:40浏览次数:18  
标签:图论 ch int 割顶 DFS 割点 dfn low 节点

前置定义

有无向图 \(G = (V, E).\)

  • 无向图的 DFS 树:从某一点 \(root\) 开始 DFS,访问邻点 \(.\) 当搜索到点 \(u\) 时,我们遍历每一条以 \(u\) 为起点的边 \((u, v_i)\),且定义有向边 \(u \longrightarrow v_i.\) 于是 DFS 的过程全部完成之后,所有被定义的有向边就会组成一颗以 \(root\) 为根树,这棵树就是图 \(G\) 的 DFS 树。
  • DFS 序:DFS 过程中,每次搜索到的节点编号组成的序列是为 DFS 序。
  • DFN(DFS number):节点在 DFS 序中的位置,即这个节点是第几个被 DFS 查找到的。下称 节点 \(v\) 的 DFN 为 \({dfn}_v\)。

    上图展示了某图的一种 DFS 树以及这种 DFS 序下对应的节点的 DFN 值。

DFS 树的重要性质

定义 \(T(x)\) 为节点 \(x\) 的子树。包括 \(x\)。

  • DFN 单调性:任意一个节点 \(u\),满足它的子树中所有的点的 \(dfn\) 值均大于等于它的 \(dfn\) 值。即 \(dfn_v \geq dfn_u[v \in T(u)]\).
  • 祖先后代性:若 \(u \longrightarrow v\) 为非树边,则必有 \(u, v\) 有祖先和后代的关系。

割点判断

所谓割点,是指在删除这个节点之后,整个图的连通块数量有增加,也就是此次删除把某个连通块分割成了两个连通块。所以整个图原来有几个连通块并不重要,重要的是删点后能否分割当前的连通块。只需思考一个连通块内求割点的方法,就可以推广到有几个连通子图的复杂图中。

如果 \(x\) 为割点,把当前连通块从 \(x\) 处分为两部分,一部分是 \(x\) 在 DFS 树上的子树 \(T(x)\),一部分是在 DFS 树上除去 \(T(x)\) 以外的部分 \(T'(x)\)。那么断开以后,产生两个块各自联通,\(T(x)\) 中的任意一点都没有办法不通过 \(x\) 到达 \(T'(x)\) 中的点了。若想不经过 \(x\),必然有一条边 \(u \longrightarrow y\) 可以到达 \(x\) 的祖先节点,绕过 \(x\)。又因为 \(T'(x)\) 自己内部联通,所以只要满足前面的条件就可以通过这条边到达 \(T'(x)\) 中的任意一点。

设 \(low_u\) 为 \(u\) 仅经过一条非树边能到达的节点中,DFN 值最小的。上面的结论可以进一步表达为:\(low_u < dfn_x\)。

如果这个节点为根节点,那么就要判断它的子树数量。如果它有超过一个的子树(即儿子),那么如果删去它,他的子树之间都不会联通了。这个判断可以通过 DFS 时通过树边访问时记录。

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n, m, num, root, cv_cnt;
int dfn[N], low[N];
bool cv_chk[N];
vector<int> g[N];
inline int read(){
    int s = 0, w = 1;
    char ch = getchar();
    while(!isdigit(ch)) { w = (ch == '-' ? -1 : 1); ch = getchar(); }
    while(isdigit(ch)) { s = s * 10 + ch - '0'; ch = getchar(); }
    return s * w;
}
inline void write(int x){
    if(x < 0) { x = -x, putchar('-'); }
    if(x > 9) write(x / 10);
    putchar(x % 10 + '0');
}
void cv(int x){
    int chc = 0;
    dfn[x] = low[x] = ++num;
    for(int y : g[x]){
        if(!dfn[y]){
            cv(y);
            chc++, low[x] = min(low[x], low[y]);
            if(low[y] >= dfn[x]){
                if(x != root || chc > 1){
                    if(!cv_chk[x])
                        cv_cnt++;
                    cv_chk[x] = true;
                }                
            }        
        }else
            low[x] = min(low[x], dfn[y]);
    }
}
int main(){
    n = read(), m = read();
    while(m--){
        int u = read(), v = read();
        g[u].push_back(v), g[v].push_back(u);
    }
    for(int i = 1; i <= n; i++)
        if(!dfn[i])
            root = i, cv(i);
    write(cv_cnt); putchar('\n');
    for(int i = 1; i <= n; i++)
        if(cv_chk[i])
            write(i), putchar(' ');
    return 0;
}

标签:图论,ch,int,割顶,DFS,割点,dfn,low,节点
From: https://www.cnblogs.com/-Prulystic-/p/18213368

相关文章

  • 图论定理汇总(二)
    第六章平面图(一)、平面图的概念定义1如果能把图GGG画在平面上,使得除顶点外,边与边之间没有交叉,称G......
  • 图论-二分图匹配匈牙利算法
    不得不说,如果以现实角度代入此算法的理解,就合理了很多,虽然有悖道德准则重点在于以下几点每次给女生分配男生前,都把男生全部初始化为可预定状态(即使他已经被别人成功匹配了)在所有女生中意的男生中遍历,如果发现该男生可预订就先预定,然后看他是否已经有主了,如果有主了,就dfs(matc......
  • 图论-割边与边双连通分量
    首先是两篇模板割边点击查看代码inthead[N],cnt=1;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,bri_cnt;//dfn......
  • 图论-割点与点双连通分量
    首先是两篇的代码割点点击查看代码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]时......
  • 关于 图论建模 的一些技巧
    分层图思想分层图在最短路中经常用到。直观上讲,就是将一个图复制k倍,互相是平行的,即互不影响,分层图两两之间会有决策边相连。这就等价于要在一个图上进行k次决策,对于每次决策,不影响图的结构,只影响目前的状态或代价。一般将决策前的状态和决策后的状态之间连接一条权值......
  • 图论-割点与割边
    这是摘自算法书上的一篇Tarjan求割点算法dfn[i]代表时间戳数组back[i]代表该点不依靠祖先节点能回到的最远的祖先节点采用链式前向星建图,结果存储在iscut[]数组中点击查看代码inthead[N],cnt=0;structEdge{intfrom,to,nxt;}e[N<<1];voidadd(......
  • 24/05/08 图论
    \(\color{purple}(1)\)CF746GNewRoads构造一棵\(n\)个点的深度为\(t\)的树,以\(1\)为根,使其中深度为\(i\)的点有\(a_i\)个且叶节点有\(k\)个。或报告无解。\(t,k\len\le2\times10^5\)。为了方便,我们令根节点的深度为\(1\)。所有读入都向后顺延一位。......
  • 24/05/07 图论
    \(\color{green}(1)\)CF711DDirectedRoads有\(n\)个点和\(n\)条边,第\(i\)条边从\(i\)连到\(a_i\)(保证\(i\nea_i\))。每条边需要指定一个方向(无向边变为有向边)。问有多少种指定方向的方案使得图中不出现环,答案对\(10^9+7\)取模。\(n\le2\times10^5\)......
  • 好题——图论
    前言本文章将会持续更新,主要是一些个人觉得比较妙的题,主观性比较强(给自己记录用的),有讲错请补充。带!号的题是基础例题,带*号的是推荐首先完成的题(有一定启发性的)。图论最短路P1119灾后重建此题看到以后以为是很简单的最短路问题(实际也不难),就写了dijkstra,然后光荣的tie......
  • 24/04/27 图论及 dfs 序相关
    \(\color{green}(1)\)CF721CJourney给定一张\(n\)个点\(m\)条边的有向无环图,边有边权。构造一条\(1\ton\)的路径使得其边权和\(\lek\)且经过的点数最多。\(n,m\le5\times10^3\),\(k\le10^9\)。最简单的想法是设状态\(f_{i,j}\)表示\(1\toi\)的边权......