图的割点问题

#include <stdio.h>
#include<stdlib.h> 
#include <cstring>
#include <iostream>
#include <string.h>
#include <sstream>
#include <math.h>

using namespace std;
int n,m,index,root;
bool vis[105];
int num[105],low[105];
int e[15][15];
void dfs(int cur,int father){                   //cur 此时节点   father 父节点 
    int child=0,i,j;                            //每次搜索 初始化孩子节点数为0 
    index++;                                         //每次深搜时间戳加一 
    num[cur]=index;
    low[cur]=index;                                  //初始化设置该点的num 和low数组 
    for(int i=1;i<=n;i++){
        if(e[cur][i]!=0){                            //生成树过程 cur作为父节点 i作为子节点 节点之间必须相连 
            if(num[i]==0){                            //如果子节点的时间戳为0 表示该节点未被访问过 
                child++;
                dfs(i,cur);                           //继续生成树 
                low[cur]=min(low[cur],low[i]);     //通过子节点更新 该节点可以到达的最小时间戳 
                if(low[i]>=num[cur]&&cur!=root){   //不为根节点的割点条件  low[i]>=num[cur]
                    vis[cur]=1;
                }
                if(cur==root&&child==2){           //根节点的割点条件    child==2
                    vis[cur]=1;
                }
            }
            else if(i!=father){                       //子节点已经被访问过 直接更新该点可以到的最小时间戳 相当于回溯找除父节点之外可到最小时间戳 
                low[cur]=min(low[cur],num[i]);
            }
        }
    }
}
int main ()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            e[i][j]=0;
        }
    }
    int x,y,v;
    for(int i=0;i<m;i++){
        cin>>x>>y;
        e[x][y]=1;
        e[y][x]=1;
    }
    root=1;
    dfs(1,root);
    for(int i=1;i<=n;i++){
        if(vis[i]){
            cout<<i<<endl;
        }
    }
    return 0;
}

首先,什么是割点?

割点就是图中的一个点,不经过这个点图就不连通了,那么这个点就是割点。如下图2这个点就是割点:

然后怎么找图的割点呢?

我们用深搜生成一颗树(不一定是最小生成树),然后用num数组记录生成这颗树过程中每个节点的时间戳(时间戳就是被访问的顺序,一般时间戳不会有相同),

用low数组记录每个节点不经过父节点可以到达的最小时间戳的祖先节点。

 

此时有一个结论:

有一个节点father,至少存在一个节点cur,有low[cur]>=num[father] (其中father是父节点,cur是father的子节点),那么father就是割点。

如果father是根节点时,除了low[cur]>=num[father]还必须father必须至少有两个孩子节点,father才是割点。

输入样例:

6 7
1 2
1 3
1 4
2 5
3 5
4 5
5 6

输出样例:

5

输入样例:

6 7
1 4
1 3
4 2
3 2
2 5
2 6
5 6

输出样例:

2

原文地址:https://www.cnblogs.com/xusi/p/12790591.html