• [kuangbin带你飞]专题九 连通图B


    判断割点的性质:

    如果点y满足

    low[y]>=dfn[x] 且不是根节点

    或者是根节点,满足上述式子的有两个及其以上。

    就是割点

    如果是起点,那么至少需要两个子节点满足上述条件,因为它是根节点,那么必须有至少两个节点的以及其儿子节点的时间戳是比这个值小的,如图,否则根节点也只是

    一个叶子节点。

    #include<iostream>
    #include<string.h>
    #include<algorithm>
    #include<stdio.h>
    using namespace std;
    const int SIZE = 100010;
    int head[SIZE],ver[SIZE*2],Next[SIZE*2];
    int dfn[SIZE],low[SIZE],stack[SIZE];
    bool cut[SIZE];
    int n,m,tot,num,root;
    void add(int x,int y)
    {
        ver[++tot]=y,Next[tot]=head[x],head[x]=tot;
    }
    void tarjan(int x)
    {
        dfn[x]=low[x]=++num;
        /*
          编号
        */
        int flag=0;
        for (int i=head[x]; i; i=Next[i])
        {   /*
            遍历
            */
            int y=ver[i];
            if (!dfn[y])
            {
                tarjan(y);
                low[x]=min(low[x],low[y]);
                if (low[y]>=dfn[x]) /*割点的性质*/
                {
                    //就是找到一个点,这个点的时间戳是比期所有子节点的最小时间戳都要小于或者等于的
                    //那么我们只能通过这个点访问这个点
                    flag++;
                    if(x!=root || flag>1)cut[x]=true;
                    //如果是根节点,那么它要是割点前提是它必须要有两个以上的子节点满足上述条件
                }
            }
            else
            {
                low[x]=min(low[x],dfn[y]);
            }
        }
    }
    void init(){
        memset(low,0,sizeof(low));
        memset(dfn,0,sizeof(dfn));
        memset(Next,0,sizeof(Next));
        memset(ver,0,sizeof(ver));
        memset(head,0,sizeof(head));
        memset(stack,0,sizeof(stack));
        memset(cut,0,sizeof(cut));
        tot=1;
        num=0;
    }
    int main()
    {
        char s[104];
        int a,b;
        char ch;
        while(scanf("%d",&n)&&n)
        {
            init();
            while(scanf("%d",&a)&&a)
            {
                while(scanf("%d%c",&b,&ch))
                {
                    add(a,b);
                    add(b,a);
                    if (ch=='
    ')break;
                }
            }
            int ans=0;
            for (int i=1; i<=n; i++)
            {
                if (!dfn[i])root=i,tarjan(i);
            }
            ans=0;
            for (int i=1; i<=n; i++)
            {
                if (cut[i])
                {
                    ans++;
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    有不懂欢迎咨询 QQ:1326487164(添加时记得备注)
  • 相关阅读:
    【必备】史上最全的浏览器 CSS & JS Hack 手册(转)
    iScroll4.2.5中的无法滑动或点击的解决方案(转)
    无障碍网页设计(WCAG2.0)
    大小端
    TCP报文结构
    A*
    shell中uniq与sort -u 两种去重的对别
    login流程
    类模板成员函数
    game 角色相关记录
  • 原文地址:https://www.cnblogs.com/bluefly-hrbust/p/11228053.html
Copyright © 2020-2023  润新知