tarjan

Posted kohano

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了tarjan相关的知识,希望对你有一定的参考价值。

用途:缩点+找环

DFN:dfs序编号
low[u]:u点所能到达的,深度最小的点的DFS序编号

DFS序:DFS过程中的顺序,可记录

low【树枝边】:dfs时将要访问的边
(判断标准:该边终点尚未被访问)
【前向边】:终点已被访问过,且在子树中的边
(判断标准:终点已被访问过,且终点dfs序>起点dfs序的边)
dfn【后向边】:终点已被访问并在栈中,且不在子树中的边
【横叉边】:终点已被访问并不在栈中,且不在子树中的边

 

【真正需要判断并用于更新的只有树枝边(用low更新)和后向边(用dfn更新).关于前向边和横叉边……他们死了】

 1 #include <iostream>
 2 using namespace std;
 3 const int maxn=10000;
 4 int dfn[maxn];//dfs序 
 5 int low[maxn];//u点所能到达的,深度最小的点的DFS序编号
 6 int dfscnt;//记录dfs序的计时器 
 7 int s[maxn],p;//
 8 int scc[maxn];//scc[u]表示强连通分量u的编号
 9 int scccnt; //表示强连通分量的数量,用作计数器 
10 
11 void tarjan(int u){
12     dfscnt++;
13     dfn[u]=low[u]=dfscnt;
14     s[p++]=u;
15     for(int i=head[u];i;i=e[i].next)
16     {
17         int v=e[i].to;
18         if(!dfn[v])    //若未被访问,判断树枝边,用low更新 
19         {
20             tarjan(v);
21             low[u]=min(low[u],low[v]);
22         }
23         else if(!scc[v])//判断后向边,用dfn更新 
24         {
25             low[u]=min(low[u],dfn[v]);
26         }    
27     }
28     if(dfn[u]==low[u])
29     {
30         scccnt++;    //强连通分量+1 
31         scc[p]=scccnt;    //令该部分的强连通编号统一 
32         while(s[p]!=u)    
33         {
34             p--;    //该强连通分量内所有节点退栈 
35             scc[p]=scccnt;    
36         } 
37         p--;    //最后将u退栈 
38     }
39 }

原理不需要理解,造轮子就完事了……

反正最后只需要用sccnum[]缩点【趴】

 

以上是关于tarjan的主要内容,如果未能解决你的问题,请参考以下文章

tarjan割点算法代码实现

tarjan(缩点)

洛谷 P2194 HXY烧情侣Tarjan缩点 分析+题解代码

关于tarjan

HDU 1269 迷宫城堡 tarjan算法求强连通分量

强连通图(tarjan)模板和详解