• tarjan算法 求桥


    边双联通分量:在一个无向图中,存在一个极大子图,删除任意一条边之后仍然是一个无向图。

    桥:在无向图中,存在某条边,删除该边之后,该无向图将会被分割成两个无向图。

      1 #include <iostream>
      2 #include <vector>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <queue>
      6 #include <map>
      7 #include <algorithm>
      8 
      9 using namespace std;
     10 
     11 #define ll long long
     12 #define pb push_back
     13 #define fi first
     14 #define se second
     15 
     16 const int N = 1e5 + 10;
     17 int dfn[N]; //时间戳
     18 int low[N]; //能到达最早点
     19 int s[N]; //
     20 int scc_no[N];//属于哪个scc
     21 int scc_cnt[N]; //该scc有几个点
     22 vector<int > scc[N];//缩点
     23 vector<int > E[N]; //
     24 vector<int > new_E[N];//缩点后的图
     25 int boss[N];
     26 int SCC; //第几个scc
     27 int tim;//dfs序号
     28 int top;//栈顶
     29 int cut_cnt; //割桥数
     30 int n, m; //点数  边数
     31 struct _cut{
     32     int x, y;
     33 };
     34 vector<_cut > cut;// 35 
     36 //时间复杂度  O(m)
     37 //无向图中求的是边双联通分量,ins[]数组没作用
     38 
     39 void init(){
     40     for(int i = 0; i <= n; ++i){
     41         dfn[i] = low[i] = 0;
     42         scc_cnt[i] = 0;
     43         scc_no[i] = 0;
     44         scc[i].clear();
     45         E[i].clear();
     46     }
     47     SCC = tim = top = cut_cnt = 0;
     48     cut.clear();
     49 }
     50 
     51 void tarjan(int now, int pre){
     52     dfn[now] = low[now] = ++tim;
     53     s[top++] = now;
     54 
     55     int pre_cnt = 0;
     56     for(auto to : E[now]){
     57         //处理一条无向边
     58         if(to == pre && pre_cnt == 0) { pre_cnt = 1; continue; }
     59 
     60         if(!dfn[to]){
     61             tarjan(to, now);
     62             low[now] = min(low[now], low[to]);
     63 
     64             //to不能到达 now或者now之前的点
     65             if(dfn[now] < low[to]){
     66                 cut.pb(_cut{now, to});
     67             }
     68 
     69         }else low[now] = min(low[now], dfn[to]);
     70     }
     71 
     72     if(dfn[now] == low[now]){
     73         int sum = 0; //该scc的点数
     74         ++SCC;//第几个scc
     75         boss[SCC] = now;
     76         int tmp;//暂存点
     77 
     78         do{
     79             tmp = s[--top];//取点
     80             ++sum;//点数++
     81             scc_no[tmp] = SCC;//属于哪个scc
     82             //scc[SCC].pb(tmp);//放入这个连通图,缩点
     83         }while(tmp != now);
     84         //scc_cnt[SCC] = sum;//该scc的点数
     85     }
     86 }
     87 //桥信息
     88 void show_info(){
     89     printf("cut bridge = (%d)
    ", cut_cnt);
     90     for(auto c : cut){
     91         printf("(%d - %d)
    ", c.x, c.y);
     92     }
     93 }
     94 
     95 void solve(){
     96 
     97     //int _case = 0;
     98     while(~scanf("%d%d", &n, &m) && (n + m)){
     99         //scanf("%d%d", &n, &m);
    100         //初始化每组数据
    101         init();
    102         
    103         //读边
    104         for(int i = 1; i <= m; ++i){
    105             int u, v;
    106             scanf("%d%d", &u, &v);
    107             E[u].pb(v);
    108             E[v].pb(u);
    109         }
    110 
    111         //可能不是一个连通图
    112         for(int now = 1; now <= n; ++now){
    113             if(!dfn[now]){
    114                 tarjan(now, now);
    115             }
    116         }
    117 
    118         cut_cnt = cut.size();
    119 
    120         show_info();
    121     }
    122 }
    123 
    124 int main(){
    125     
    126     solve();    
    127     //cout << "not error" << endl;
    128     return 0;
    129 }
  • 相关阅读:
    vue.api
    v-resource
    vue.js路由
    computed watch methods
    vue.js生命周期
    flex布局
    字符截取 slice substr substring
    原生Ajax书写
    jq动画
    css 3动画
  • 原文地址:https://www.cnblogs.com/SSummerZzz/p/13039760.html
Copyright © 2020-2023  润新知