zoukankan      html  css  js  c++  java
  • 图的割点问题

    #include <stdio.h>
    #include<stdlib.h> 
    #include <cstring>
    #include <iostream>
    #include <string.h>
    #include <sstream>
    #include <math.h>
    
    using namespace std;
    int n,m,index,root;
    bool vis[105];
    int num[105],low[105];
    int e[15][15];
    void dfs(int cur,int father){                   //cur 此时节点   father 父节点 
        int child=0,i,j;                            //每次搜索 初始化孩子节点数为0 
        index++;                                         //每次深搜时间戳加一 
        num[cur]=index;
        low[cur]=index;                                  //初始化设置该点的num 和low数组 
        for(int i=1;i<=n;i++){
            if(e[cur][i]!=0){                            //生成树过程 cur作为父节点 i作为子节点 节点之间必须相连 
                if(num[i]==0){                            //如果子节点的时间戳为0 表示该节点未被访问过 
                    child++;
                    dfs(i,cur);                           //继续生成树 
                    low[cur]=min(low[cur],low[i]);     //通过子节点更新 该节点可以到达的最小时间戳 
                    if(low[i]>=num[cur]&&cur!=root){   //不为根节点的割点条件  low[i]>=num[cur]
                        vis[cur]=1;
                    }
                    if(cur==root&&child==2){           //根节点的割点条件    child==2
                        vis[cur]=1;
                    }
                }
                else if(i!=father){                       //子节点已经被访问过 直接更新该点可以到的最小时间戳 相当于回溯找除父节点之外可到最小时间戳 
                    low[cur]=min(low[cur],num[i]);
                }
            }
        }
    }
    int main ()
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                e[i][j]=0;
            }
        }
        int x,y,v;
        for(int i=0;i<m;i++){
            cin>>x>>y;
            e[x][y]=1;
            e[y][x]=1;
        }
        root=1;
        dfs(1,root);
        for(int i=1;i<=n;i++){
            if(vis[i]){
                cout<<i<<endl;
            }
        }
        return 0;
    }

    首先,什么是割点?

    割点就是图中的一个点,不经过这个点图就不连通了,那么这个点就是割点。如下图2这个点就是割点:

    然后怎么找图的割点呢?

    我们用深搜生成一颗树(不一定是最小生成树),然后用num数组记录生成这颗树过程中每个节点的时间戳(时间戳就是被访问的顺序,一般时间戳不会有相同),

    用low数组记录每个节点不经过父节点可以到达的最小时间戳的祖先节点。

     

    此时有一个结论:

    有一个节点father,至少存在一个节点cur,有low[cur]>=num[father] (其中father是父节点,cur是father的子节点),那么father就是割点。

    如果father是根节点时,除了low[cur]>=num[father]还必须father必须至少有两个孩子节点,father才是割点。

    输入样例:

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

    输出样例:

    5

    输入样例:

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

    输出样例:

    2

  • 相关阅读:
    Android -- ConditionVariable
    Android -- startActivityForResult和setResult
    StringTokenizer
    Android -- java代码设置margin
    Android -- DisplayMetrics
    Android -- TypedArray
    Android -- 屏幕亮度
    Java assert
    Android -- com.android.providers.media,external.db
    Inno Setup入门(十)——操作注册表
  • 原文地址:https://www.cnblogs.com/xusi/p/12790591.html
Copyright © 2011-2022 走看看