zoukankan      html  css  js  c++  java
  • tarjan算法 求割点

    点双连通分量:在一个无向图中,存在一个极大子图,删除任意一个节点之后该图仍然是一个连通图。

    割点:在一个无向图中,存在一个节点,删除这个节点之后,该无向图会被分为若干个连通图(个数大于一),则该点为割点。

    #include <iostream>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <map>
    
    using namespace std;
    
    #define ll long long
    #define pb push_back
    #define fi first
    #define se second
    
    const int N = 2e4 + 10;
    int dfn[N]; //时间戳
    int low[N]; //能到达最早点
    int cut[N]; //是否是割点
    vector<int > E[N]; //
    int tim;//dfs序号
    int root; //每个连通图的出发点
    int cut_cnt; //割点数量
    int n, m; //点数  边数
    
    
    //时间复杂度  O(m)
    //割点条件
    //(1)该点为最初点root,且该点之下至少存在左图和右图
    //(2)该点不u为root,但是该点之后的点无法到达u之前的点
    
    void init(int n){
        for(int i = 1; i <= n; ++i){
            dfn[i] = low[i] = 0;
            cut[i] = 0;
            E[i].clear();
        }
        tim = cut_cnt = 0;
    }
    
    void tarjan(int now, int pre){
        dfn[now] = low[now] = ++tim;
    
        int son = 0;//图个数
        for(auto to : E[now]){
            
            if(to == pre) continue;
    
            if(!dfn[to]){
                ++son;
                tarjan(to, now);
                low[now] = min(low[now], low[to]);
                //(2)该点不u为root,但是该点之后的点无法到达u之前的点
                if(now != root && dfn[now] <= low[to]) cut[now] = 1;
            }else low[now] = min(low[now], dfn[to]);
        }
    
        //(1)该点为最初点root,且该点之下至少存在左图和右图
        if(now == root && son > 1) cut[now] = 1;
    }
    
    void show_info(){
    
        //割点数量
        printf("
    cut point 's number = %d
    ", cut_cnt);
        //割点信息
        printf("they' re : ");
        for(int i = 1; i <= n; ++i){
            if(cut[i]) printf("(%d) ", i);
        }
        printf("
    
    ");
    }
    
    
    void solve(){
    
        while(~scanf("%d%d", &n, &m)){
            //scanf("%d%d", &n, &m);
            //初始化每组数据
            init(n);
            
            //读边
            for(int i = 1; i <= m; ++i){
                int u, v;
                scanf("%d%d", &u, &v);
                E[u].pb(v);
                E[v].pb(u);
            }
    
            //可能不是一个连通图
            for(int now = 1; now <= n; ++now){
                if(!dfn[now]){
                    root = now;
                    //这样可以防止自环的情况
                    tarjan(now, now);
                }
            }
            //统计割点个数
            for(int i = 1; i <= n; ++i){
                if(cut[i]) ++cut_cnt;
            }
            show_info();
        }
    }
    
    int main(){
        
        solve();    
        //cout << "not error" << endl;
        return 0;
    }
  • 相关阅读:
    [Bootstrap]全局样式(四)
    [Bootstrap]全局样式(三)
    [Bootstrap]全局样式(二)
    [Bootstrap]全局样式(一)
    [Bootstrap]概述
    原生JS-----一个剪刀石头布游戏
    聊聊 ES6 中的箭头函数
    jQuery中的 AJAX
    AJAX封装
    AJAX 初识
  • 原文地址:https://www.cnblogs.com/SSummerZzz/p/13032794.html
Copyright © 2011-2022 走看看