zoukankan      html  css  js  c++  java
  • Tarjan算法

    首先我们需要知道强连通分量,因为Tarjan就是用来求这个的。连通的意思是对于<u,v>,存在路径可以从其中一个达到另一个;强连通是指即存在从u到v的路径,又存在从v到u的路径。强连通是针对于有向图来说的,因为无向图只要做到了连通就做到了强连通。强连通分量就是指有向图的极大强连通子图,多一个点少一个点都不能保证强连通。

    求一个有向图的强连通分量有三种常用算法,Kosaraju算法、Tarjan算法、Gabow算法。其中最最常用且效率很高的是Tarjan算法。

    Tarjan算法利用了dfs,定义dfn[u]表示结点u的时间戳(第几个被访问的),low[u]表示从结点u向下遍历所能找到的最小的dfn。强连通分量里必然存在环,从其中一个结点向下遍历必然会回到自身,而low中存放的是找到最小的dfn,假若一个结点的dfn=low,那么他一定是强连通分量中第一个被访问到的点。如果我们使用栈保存被访问过的结点,那么从这个结点开始往上直到栈顶就是当前强连通分量中的点。

    如果我们把所有的强连通分量找出来,缩成一个点,那么这个图将变成DAG,因为不再有环。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<stack>
     5 using namespace std;
     6 int n,m,head[maxn],eid;
     7 struct edge {
     8     int v,next;
     9 } E[maxm];
    10 void insert(int u,int v) {
    11     E[eid].v=v;
    12     E[eid].next=head[u];
    13     head[u]=eid++;
    14 }
    15 int dfn[maxn],low[maxn],ins[maxn],vid,scc,belong[maxn];
    16 stack<int> s; //用栈存放已访问的结点
    17 void tarjan(int u) {
    18     dfn[u]=low[u]=vid++; //初始化,打时间戳
    19     s.push(u); //结点入队,同时记录结点是否在队列中
    20     ins[u]=1; //不在队列中可视为属于其他强连通分量
    21     for(int p=head[u];p+1;p=E[p].next) {
    22         int v=E[p].v;
    23         if(!dfn[v]) { //对于未访问过的结点
    24             tarjan(v);
    25             low[u]=min(low[u],low[v]); //更新最早的时间戳
    26         } else if(ins[v]) low[u]=min(low[u],dfn[v]);
    27     } //若v在栈中,说明属于当前强连通分量,也要考虑他的时间戳
    28     //最后low里就是从该结点出发能找到的最小的时间戳
    29     if(dfn[u]==low[u]) { //说明该结点是当前强连通分量最早被标记的点
    30         ++scc;
    31         while(!s.empty()) {
    32             int t=s.top();s.pop();
    33             ins[t]=0; //记得更新ins
    34             belong[t]=scc;
    35             if(t==u) break;
    36         }
    37     }
    38 }

    只从一个结点出发并不一定能找全图上所有的SCC,所以需要进行多次Tarjan。

    for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
  • 相关阅读:
    Servlet CDI Example Analysis
    JSON续
    JSON
    Ubuntu 下安装 MySQL
    Filter介绍
    Annotation相关
    Container、Injection
    Java buildTools
    Http协议
    URI URL URN 的区别
  • 原文地址:https://www.cnblogs.com/Mr94Kevin/p/9651975.html
Copyright © 2011-2022 走看看