network tarjan算法求割点

48 篇文章 0 订阅
46 篇文章 0 订阅
#include <stdio.h>
#include <cstring>
struct edge
{
    int next,to;
} e[10001];
int dfn[101];
int low[101];
int head[101];
int ans[101];
int n,tot,root=1,num;
void add(int a,int b)
{
    e[tot].to=b;
    e[tot].next=head[a];
    head[a]=tot++;
}
inline int min(int a,int b)
{
    return a<b?a:b;
}
void tarjan(int u,int ufa)
{
    int rootson=0;//根节点的儿子节点数目,如果大于1,则根节点是割点
    low[u]=dfn[u]=++num;//标记次序的节点编号一定要从1开始
    for(int i=head[u]; i!=-1; i=e[i].next)
    {
        int j=e[i].to;
        if(!dfn[j])
        {
            if(u==root)//根的情况要特殊处理,j不可能等于root,j是u的子节点
            {
                if(++rootson>1) ans[u]=true;
            }
            tarjan(j,u);//u是j的父节点
            low[u]=min(low[j],low[u]);//low值是更新当前的父节点,利用儿子节点的low来更新
            if(u!=root&&dfn[u]<=low[j])//根的情况已经讨论,避免重复
                ans[u]=true;//都是对目前传入的父亲节点进行讨论,不能置其子节点为true.
        }
        else if(j!=ufa)
            low[u]=min(low[u],dfn[j]);
    }
}
int main()
{
    while(scanf("%d",&n)==1&&n)
    {
        memset(head,-1,sizeof(head));
        tot=0,num=0;
        int i,j;
        char ch;
        while(scanf("%d",&i)==1&&i)//根据题意的输入顺序一个数字一个空格
        {
            while((ch=getchar()!='\n'))
            {
                scanf("%d",&j);
                add(i,j);
                add(j,i);
            }
        }
        memset(ans,false,sizeof(ans));
        memset(low,0,sizeof(low));
        memset(dfn,0,sizeof(dfn));
        tarjan(root,-1);//初始节点置为1,其父亲节点置为-1
        int count=0;
        for(int i=1; i<=n; i++)
        {
            if(ans[i]) count++;
        }
        printf("%d\n",count);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值