zoukankan      html  css  js  c++  java
  • 图的割点与割边

    话说割点概念,应该很好理解:

    一个图,如果一个点消失,这个点就不连通,那么这个点就是这个图的割点(无向图)

    举个例子:

    很明显,4就是这个图的割点。

    所以怎么求割点呢??

    来来来,先上数据:

    6 6
    1 2
    1 3
    3 4
    2 4
    4 5
    4 6

    嗯,注意这是无向图!!!

    做法是这样的

    首先,记录每一个点的时间截,也就是dfs第几次搜索到这个点,时间截图如下:

    之后,记录每个节点在不经过自己的节点范围内,最小的时间截。

    例如从3号点搜索到的4,那么4号点的最小时间截为1号点的1

    再例如从4到达的5,那么5的最小时间截是4号点的3(注意可以到达4号点,只是不能经过)

    最后,如果一个点的时间截>=它的下一个点的最小时间截,那么这个点就是割点。

    举个例子:4号点的下一个点有5和6和2,以5举例,5的最小时间截是3,4的时间截是3,>=5号点最小时间及偶尔,所以4号点是割点。

    代码实现我们用到的是dfs,开始每个点的最小时间截,就是自己本身的时间截,然后在通过一条一条边,不断变少。

    先呈上代码,然后我们来模拟一下dfs过程:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    using namespace std;
    int n,m;
    int root;
    int total=0;
    int index=0;
    int head[100010];
    int book[100010];
    int num[100010],low[100010];
    struct edge
    {
        int from;
        int to;
        int next;
    }input[100010];
    void add_edge(int a,int b)
    {
        total++;
        input[total].from=a;
        input[total].to=b;
        input[total].next=head[a];
        head[a]=total;
    }
    void dfs(int now,int father)
    {
        index++;
        int child=0;
        num[now]=index;
        low[now]=index;
        for(int e=head[now];e!=0;e=input[e].next)
        {
            if(num[input[e].to]==0)
            {
                child++;
                dfs(input[e].to,now);
                low[now]=min(low[now],low[input[e].to]);
                if(now!=root && low[input[e].to]>=num[now])
                    book[now]=true;
                if(now==root && child==2)
                    book[now]=true;
            }
            else if(input[e].to!=father)
                low[now]=min(low[now],num[input[e].to]);
        }
    }
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=m;i++)
        {
            int a,b;
            cin>>a>>b;
            add_edge(a,b); 
            add_edge(b,a);
        }
        root=1;
        dfs(1,root); 
        for(int i=1;i<=n;i++)
            if(book[i])
                cout<<i<<" ";
    }

    开始还是一直递归,1——3——4——6

    然后发现6无法递归,于是返回

    到4,发现自己的最小时间截(以下简称low)比6的4要小,所以不改变。

    然后到5,发现low还是比5的5要小,所以不改变。

    接着到2,发现2的时间截还是更大,所以不改变。返回。

    此时,2、5、6的low都比4的时间截大,所以4为截点

    之后,发现从一号点每一个连着的点都被走过,所以循环终止

    4为截点。

    割点完毕。

    然后割边

    一句话,割边就删一个等于号就好啦。

    至于为什么很好想吧?

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    using namespace std;
    int n,m;
    int total=0;
    int index=0;
    int head[100010];
    int num[100010],low[100010];
    struct edge
    {
        int from;
        int to;
        int next;
    }input[100010];
    void add_edge(int a,int b)
    {
        total++;
        input[total].from=a;
        input[total].to=b;
        input[total].next=head[a];
        head[a]=total;
    }
    void dfs(int now,int father)
    {
        index++;
        num[now]=index;
        low[now]=index;
        for(int e=head[now];e!=0;e=input[e].next)
        {
            if(num[input[e].to]==0)
            {
                dfs(input[e].to,now);
                low[now]=min(low[now],low[input[e].to]);
                if(low[input[e].to]>num[now])
                    cout<<now<<"->"<<input[e].to<<endl;
                    
            }
            else if(input[e].to!=father)
                low[now]=min(low[now],num[input[e].to]);
        }
    }
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=m;i++)
        {
            int a,b;
            cin>>a>>b;
            add_edge(a,b); 
            add_edge(b,a);
        }
        dfs(1,1); 
    }

    嗯,就关注

  • 相关阅读:
    自动支持图片webp格式压缩,图片服务器升级webserver
    长江商学院介绍及名人校友名单
    恒大许家印靠斗着地主,当上首富
    用GitLab搭建自己的私有GitHub
    vim快速定位到某一行的几种方法和显示行号,定位匹配字符串,显示当前行信息的命令
    mysql数据库表上百万记录优化思路杂谈
    Java打印输出数组的三种方式:传统的for循环方式,for each循环,利用Arrays类中的toString方法
    个人快速成长之系统方法,最小化成长系统
    程序员应该了解的常见软件开发定律
    用python修改文件内容修改txt内容的3种方法
  • 原文地址:https://www.cnblogs.com/jason2003/p/7603886.html
Copyright © 2011-2022 走看看