码迷,mamicode.com
首页 > 其他好文 > 详细

tarjan

时间:2019-10-26 23:17:41      阅读:125      评论:0      收藏:0      [点我收藏+]

标签:for   strong   pre   class   size   void   names   表示   iostream   

用途:缩点+找环

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

标签:for   strong   pre   class   size   void   names   表示   iostream   

原文地址:https://www.cnblogs.com/kohano/p/11745673.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!