zoukankan      html  css  js  c++  java
  • 图论:割点和桥

    一、相关概念

    1、点连通度:最小V的点数(一个图的点的连通度是最小割点集合中的顶点数)

    2、边连通度:最小E的边数(一个图的边的连通度是最小割边集合中的顶点数)

    3、割点:去掉割点这个图不连通(点连通度为1时,V的唯一元素)

    4、割边(桥):去掉割边这个图不连通(边连通度为1时,E的唯一元素)

    5、双连通图:

    如果一个无向图的点连通度大于1,则是点双联通;

    如果一个无向图的边连通度大于1,则是边双联通。

    6、双联通分量:

    在图G中,G’是G的子图,G’双联通,则G’是双联通分量。

    (双联通分量一定是点双联通分量,但不一定是边双联通分量)

    7、双连通性:将无向图的任意顶点删除后,剩下的图依然连通,那么这样的图是双联通的。

    二、割点的求解方法

    1、无向图的深度优先生成树:

    将对无向图进行深度优先遍历的顺序作为树节点的编号,建立正向边;

    相反的,如果遍历到已经存在的节点,建立相应的背向边。

    2、求解割点的过程:

    (1)建立Num(v),按照深搜的顺序给节点编号(先序遍历编号)

    (2)建立Low(v)的三原则:(后序遍历)

    Num(v);

    所有背向边(v,w)中最低的Num(w);

    所有边(v,w)中最低的Low(w);

    (3)割点的条件

    如果是根节点:有一个以上的儿子;

    如果不是根节点:Low(v)>= Num(v)。

    (具体实现的细节:

    (1)可以让根节点就是割点然后建立深搜树,再求割点;

    (2)也可以记录每个节点的儿子的数量然后分别判断根节点与非根节点)。

    3、实现:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    using namespace std;
    const int maxn = 1200;
    const int INF = 0x3ffffff;
    int num[maxn],parent[maxn],low[maxn],vis[maxn],cnt;
    vector <int> vc[maxn];
    int MIN(int x,int y)
    {
        return x<y?x:y;
    }
    void AssignNum(int v) //建立dfs深搜树 
    {
        int i,w;
        num[v]=cnt++;
        vis[v]=1;
        for(i=0;i<vc[v].size();i++){
            w=vc[v][i];
            if(vis[w]==0){
                parent[w]=v;
                AssignNum(w);
            }
        }
    }
    void AssignLow(int v) //建立low数组,打印割点 
    {
        int i,w;
        low[v]=num[v];
        for(i=0;i<vc[v].size();i++){
            w=vc[v][i];
            if(num[w]>num[v]){
                AssignLow(w);
                if(low[w]>=num[v]){
                    printf("The gedian is %d
    ",v);
                }
                low[v]=MIN(low[v],low[w]);
            }
            else if(parent[v]!=w){
                low[v]=MIN(low[v],num[w]);
            }
        }
    }
    void FindArt(int v) //打印割点 = AssignNum+AssignLow; 
    {
        int i,w;
        low[v]=num[v]=cnt++;
        vis[v]=1;
        for(i=0;i<vc[v].size();i++){
            w=vc[v][i];
            if(!vis[w]){
                parent[w]=v;
                FindArt(w);
                if(low[w]>=num[v]) printf("The articulation point is %d
    ",v);
                low[v]=MIN(low[v],low[w]);
            }
            else if(parent[v]!=w) low[v]=MIN(low[v],num[w]);
        }
    }
    int main(void)
    {
        int n,m,i,j,x,y;
        cin>>n>>m;
        cnt=1;
        memset(vis,0,sizeof(vis));
        for(i=0;i<m;i++){
            scanf("%d%d",&x,&y);
            vc[x].push_back(y);
            vc[y].push_back(x);
        }
        //AssignNum(3);
        //AssignLow(3);
        FindArt(4); //根节点是割点 
        return 0;
    }
    
    /*
    7 8
    1 2
    2 3
    3 4
    4 1
    4 7
    4 5
    7 5
    3 6
    */
    View Code

    三、桥的求解方法

    一条无向边(u,v)是桥当且仅当(u,v)是深搜树的树枝边且满足Num(u)< Low(v)。

                if(num[v]<low[w]) printf("---The edge (%d,%d) is artedge
    ",v,w);  //求割边 
  • 相关阅读:
    swagger2 Could not resolve pointer: /definitions
    mybatis-plus使用Oracle函数生成主键
    WebLogic安装及部署
    windows下用bat启动jar包,修改cmd标题(title)
    Windows下修改Tomcat黑窗口标题
    jar包注册为Linux服务
    Redis我想入门——数据类型
    Redis我想入门——启动
    JAVA8给我带了什么——Optional和CompletableFuture
    JAVA8给我带了什么——并行流和接口新功能
  • 原文地址:https://www.cnblogs.com/2018zxy/p/10357435.html
Copyright © 2011-2022 走看看