图论——无向图点双连通分量(求割点)

这篇博客介绍了如何解决无向图中删除一个点后连通块最多能分成多少个的问题。通过使用深搜(Tarjan算法)来判断割点,从而简化复杂度。当图中存在环时,直接使用DFS会变得复杂,而割点的概念使得问题求解更加高效。文章详细阐述了算法实现,并提供了C++代码示例。
摘要由CSDN通过智能技术生成

无向图点双连通分量(求割点)

题意:给定一个由 n 个点 m 条边构成的无向图,请你求出该图删除一个点之后,连通块最多有多少。
如果这个图是一个树的话啊,那么可以用dfs求解O(N)但是是一个图可能存在环用dfs会相当麻烦,因此利用割点来求会方便很多。对于整个图来说假如有cnt个连通块,如果一个连通块i不存在割点,那么最大值就是cnt + 1, 如果连通块存在割点,那么最大值就是cnt - 1 + x(删除割点剩余的连通块数目 + x本身算一个点);

const int N = 10010, M = 30010;
int n, m,h[N], e[M], ne[M], idx,dfn[N], low[N], timestamp,root, ans;
void add(int a, int b)
{e[idx] = b; ne[idx] = h[a]; h[a] = idx ++ ;}
void tarjan(int u)
{
    dfn[u] = low[u] = ++ timestamp;
    int cnt = 0;//当前块内 已经可以分出来的子树的个数
    for (int i = h[u]; ~i; i = ne[i])
    {
        int j = e[i];
        if (!dfn[j])//没有遍历过j
        {
            tarjan(j);
            low[u] = min(low[u], low[j]);//用j更新u
            if (low[j] >= dfn[u]) cnt ++ ;//j为割点 则多一个连通块
        }
        else low[u] = min(low[u], dfn[j]);
    }
    if (u != root) cnt ++ ;// 如果u不是根节点 再把u的父节点的连通块加上
    ans = max(ans, cnt);
}
int main()
{
    while (cin >> n >> m, n || m)
    {
        memset(dfn, 0, sizeof dfn);  memset(h, -1, sizeof h); idx = timestamp = 0;
        while (m -- )
        {
            int a, b; cin >> a >> b;  add(a, b), add(b, a);
        }
        ans = 0;//把每个点删完后 最多能分为几块
        int cnt = 0;//连通块数量
        for (root = 0; root < n; root ++ )
            if (!dfn[root])//如果点root没搜索过 连通块数+1
                cnt ++ ,tarjan(root);
        cout << ans + cnt - 1 << endl;
    }
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值