在无向图中求割点

 割点的定义:
 在一个无向图中,去掉某一个点,该无向图不再连通,这样的点称为割点
 
求点割集的方法:利用tarjan算法的思想,用数组dfn[v]存储DFS遍历到点v的时间,数组low[v]存储点v能追溯到最早的祖先节点。

  • 判断一点是否是割点:
    1.如果这个点是根节点并且这割点有不少于两个儿子则该节点一定是割点(去掉根节点的树其他的分支一定不再连通)
  • 如果这个点v不是根节点,但是这个点存在一个儿子low[i]>=dfn[v];(说明要到i必须经过v)则v一定是一个割点

  • 实现算法

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
const int V = 110  ;
vector<int>mp[V];//储存图
int low[V],dfn[V],numlock[V];
int sum,numson,deep;
int vis[V];

void init()
{
    memset(dfn, 0, sizeof(dfn));
    memset(vis, 0, sizeof(vis));
    memset(numlock, 0, sizeof(numlock));
    memset(low, 0, sizeof(low));
    memset(mp, 0, sizeof(mp));
    numson = sum = deep = 0;
}

void dfs(int x){
    deep ++;//递归的深度
    low[x] = dfn[x] = deep;
    vis[x] = 1;//表示已经访问过
    for(int i=0;i<mp[x].size();i++){
        int  y = mp[x][i];
        if(!vis[y]){
            dfs(y);
            low[x] = min(low[x], low[y]);//得到最早的祖先
            if(low[y]>=dfn[x]&&x!=1)numlock[x]++;
            else if(x==1)numson++;//这点是根节点,儿子数+1
        }
        else low[x] = min(low[x], dfn[y]);//已经访问过,说明已经在栈中,有圈的形成,更新low[x]取最小值
        }
}
int main()
{
    int n;
    while(scanf("%d",&n)&&n){
        init();
        int x,y;
        while (scanf("%d",&x)&&x) {
            while(getchar()!='\n'){
                scanf("%d",&y);
                mp[x].push_back(y);
                mp[y].push_back(x);
            }
            }
        dfs(1);
        for(int i=1;i<=n;i++)
            if(numlock[i])sum++;
        if(numson>1)sum++;
        printf("%d\n",sum);
        }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用Python实现无向图的最小割点集的示例代码: ``` from collections import defaultdict def min_cut_points(graph): n = len(graph) low = [0] * n dfn = [0] * n cut_points = set() def dfs(u, parent, time): children = 0 low[u] = dfn[u] = time for v in graph[u]: if not dfn[v]: children += 1 dfs(v, u, time + 1) low[u] = min(low[u], low[v]) if parent == -1 and children > 1: cut_points.add(u) elif parent != -1 and low[v] >= dfn[u]: cut_points.add(u) elif v != parent: low[u] = min(low[u], dfn[v]) for i in range(n): if not dfn[i]: dfs(i, -1, 1) return cut_points ``` 该函数接受一个字典,表示无向图的邻接表。它返回一个集合,其中包含无向图的最小割点集。 该算法使用了深度优先搜索来查找割点。对于每个节点,它维护了两个数组:dfn和low。dfn表示节点被发现的时间,low表示节点和它可达的节点之间的最小dfn值。 在搜索过程中,如果一个节点v未被发现,则将它标记为已发现,并为它更新dfn和low值。对于每个邻居节点v,如果v是u的父节点,则children计数器加1。如果v不是u的父节点,并且low[v] >= dfn[u],则u是一个割点。如果u是根节点并且children大于1,则u也是一个割点。 最终,返回所有割点的集合。 下面是一个使用示例: ``` graph = defaultdict(list) graph[0] = [1, 2] graph[1] = [0, 2] graph[2] = [0, 1, 3] graph[3] = [2, 4, 5] graph[4] = [3] graph[5] = [3] cut_points = min_cut_points(graph) print(cut_points) # 输出 {2, 3} ``` 这个例子中,图包含6个节点和7条边。最小割点集包括节点2和节点3。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值