zoukankan      html  css  js  c++  java
  • tarjan算法求强连通分量

    第一篇博客,尽管园龄已经一年了。。

     

    tarjan算法求强连通分量

    有种tarjan算法是求强连通分量的。

    那强连通分量是啥呢?

    在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通。如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向图的极大强连通子图,称为强连通分量。

    (如还不懂就点

    such as:

     

    该图中共有三个强连通分量,分别为【1,2,3,4】、【5】、【6】。

    1,2,3,4之间可以相互到达,而5和6只能到达自己,所以分成了以上三个分量。

    要找强连通分量,使用链表与深搜结合的办法:

    建好表后,以每一个点为起点都深搜一次,这里需要维护两个数组,一个是dfn[N],一个是low[N]。

    dfn[v]表示顶点v被访问的时间,low[v]表示与顶点v邻接的未删除的顶点u的low[v]与low[u]的最小值。

    在深搜的回溯过程中,如果dfn[v]==low[v],那么当前顶点就是一个强连通分量的根(由于不断维护low数组,所以该强连通分量中所有节点的low都为第一遍深搜时时间。如果不是强连通分量的根,那么一定属于另一个强连通分量,而且它的根是当前顶点的祖宗,那么存在包含当前顶点的到其祖宗的回路,可知low[v]一定会被更改为一个比dfn[v]更小的值

    下附代码

     

     1 #include<cstdio>
     2 #include<stack>
     3 #define N 420000
     4 using namespace std;
     5 stack<int>p; 
     6 struct hehe{ 
     7     int next;
     8     int to;
     9 }edge[N];
    10 int head[N],num_edge;
    11 int time;
    12 int dfn[N]; 
    13 int low[N]; 
    14 int ans1,ans2;
    15 int x,y,n,m;
    16 int place[N];
    17 bool f[N]; 
    18 bool k;
    19 void add_edge(int from,int to){ 
    20     edge[++num_edge].next=head[from];
    21     edge[num_edge].to=to;
    22     head[from]=num_edge;
    23 }
    24 void dfs(int x){
    25     k=0;
    26     p.push(x);
    27     dfn[x]=low[x]=++time; 
    28     for(int i=head[x];i;i=edge[i].next){
    29         if(f[edge[i].to]) 
    30             continue;
    31         if(dfn[edge[i].to])
    32             low[x]=min(low[x],dfn[edge[i].to]); 
    33         else{ 
    34             dfs(edge[i].to);
    35             low[x]=min(low[x],low[edge[i].to]);
    36         }
    37     }
    38     if(low[x]==dfn[x]){
    39         ++ans2;
    40         while(p.top()!=x){
    41             f[p.top()]=1; 
    42             printf("%d ",p.top()); 
    43             place[p.top()]=ans2; 
    44             p.pop(); 
    45             k=1;
    46         }
    47         f[p.top()]=1;
    48         place[p.top()]=ans2;
    49         p.pop();
    50         printf("%d
    ",x);
    51         if(k)++ans1;
    52     }
    53 }
    54 int main(){
    55     scanf("%d%d",&n,&m); 
    56     for(int i=1;i<=n;i++)
    57         f[i]=0;
    58     for(int i=1;i<=m;i++){
    59         scanf("%d%d",&x,&y);
    60         add_edge(x,y); 
    61     }
    62     for(int i=1;i<=n;i++)
    63         if(dfn[i]==0){ 
    64             time=0; 
    65             dfs(i);
    66         }
    67     printf("%d
    ",ans1); 
    68     printf("%d
    ",ans2); 
    69     for(int i=1;i<=n;++i)
    70         printf("%d ",place[i]); 
    71     return 0;
    72 }
    View Code
  • 相关阅读:
    169_Majority Element
    171_Excel Sheet Column Number
    217_Contains Duplicate
    242_Valid Anagram
    【findIndex】根据数组对象某一元素的id,找到此元素在数组所在的位置
    【鼠标右击组件】v-contextmenu
    【 拖拽组件】基于 Sortable.js 的 Vue 拖拽组件。 访问地址:Vue.Draggable
    【vue-markdown编辑器】vue-markdown 组件github地址
    mac下如何制作windows启动盘
    【vue webstorm】WebStorm Vue代码格式错误
  • 原文地址:https://www.cnblogs.com/jsawz/p/6709615.html
Copyright © 2011-2022 走看看