UVA 315 Tarjan求割点

本文详细介绍了如何在无向连通图中检测关键点,即割点的数量。通过使用Tarjan算法,文章提供了完整的C++代码实现,展示了如何确定一个点是否为关键点的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:

一个无向连通图,若去掉某个点后这个图变成了非连通图,这个点成为关键点,求关键点的数目。

题解:

1.关键点就是割点,套用Tarjan模板:https://www.cnblogs.com/collectionne/p/6847240.html

#include <bits/stdc++.h>
#define N 105
#define inf 0x3f3f3f3f
#define mod 1000000007
using namespace std;
int n ;
bool vis[N] ;
int low[N] ;
int dfn[N] ;
int parent[N] ;
bool cut_point[N] ;
vector <int> edge[N] ;
void Tarjin(int u , int m)
{
    int i , j ;
    int v ;
    int children = 0 ;
    vis[u] = 1 ;
    dfn[u] = m ;
    low[u] = m ;
    for(i = 0 ; i < edge[u].size() ; i ++)
    {
        v = edge[u][i] ;
        if(!vis[v])
        {
          children ++ ;
          parent[v] = u ;
          Tarjin(v , m + 1) ;
          low[u] = min(low[u] , low[v]) ;
          if(parent[u] == -1 && children >= 2) //u是根节点且子树数目大于等于2
             cut_point[u] = 1 ;
          if(parent[u] != -1 && low[v] >= dfn[u]) //u不是根节点且子节点的low不小于自己的dfn
             cut_point[u] = 1 ;
        }
        else if(parent[u] != v)
           low[u] = min(low[u] , dfn[v]) ;
    }
}
int main()
{
    int i , j ;
    int u , v ;
    int ans = 0 ;
    char c ;
    while(scanf("%d" , &n) && n != 0)
    {
        for(i = 1 ; i <= n ; i ++)
            edge[i].clear() ;
        while(scanf("%d" , &u) && u != 0)
        {
            while(1)
            {
                scanf("%d%c" , &v , &c) ;
                edge[u].push_back(v) ;
                edge[v].push_back(u) ;
                if(c == '\n')
                   break ;
            }
        }
        memset(low , inf , sizeof(low)) ;
        memset(dfn , inf , sizeof(dfn)) ;
        memset(parent , -1 , sizeof(parent)) ;
        memset(vis , 0 , sizeof(vis)) ;
        memset(cut_point , 0 , sizeof(cut_point)) ;
        Tarjin(1 , 1) ;
        ans = 0 ;
        for(i = 1 ; i <= n ; i ++)
            if(cut_point[i])
              ans ++ ;
        printf("%d\n" , ans) ;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值