博客
关于我
Tarjan算法(模板)
阅读量:279 次
发布时间:2019-03-03

本文共 1250 字,大约阅读时间需要 4 分钟。

算法思想: 首先要明确强连通图的概念,一个有向图中,任意两个点互相可以到达;什么是强连通分量?有向图的极大连通子图叫强连通分量。

给一个有向图,我们用Tarjan算法把这个图的子图(在这个子图内,任意两个点可以相互到达,极大的子图)缩成一个点,相当于化简;
怎样去做:从一个点开始遍历它能走到的下一个点(dfn记录时间戳,low记录能回到的最早的时间戳),每遍历到一个点,判断这个点如果没有走过(dfn值为零),继续深搜,如果走过了并且在栈里面说明可以形成一个环(那就可以缩成一个点,更新当前点low的值,回到更早的时间戳),搜完它可以到达所有的点以后回溯,更新low;直到回到 low[u]==dfn[u](环的“根节点"),出栈这个点上面的所有的点(包括这个点本身,他们可以缩成一个点).继续回溯.
特别注意:

else if(instack[v])/*走过并且形成一个环??????*/            low[u]=min(low[u],dfn[v]);/*更新最小值low,合并集合*/            /*不能写成low[u]=min(low[v],low[u])*/

当计算有多少个强连通分量的时候,写成那个没关系,但是如果是求割点,两个语句求出来的low值不一样,值会偏小,割点判断错误(因为判断条件是if(low[v]>=dfn[u]))。

扩展:
计算出入度,问加多少条边可以变成一个整个连通分量:
在这里首先缩点,用一个color[ ]数组,将同一集合的点标记成某个序号(出栈的时候就是同一集合),最后遍历输入的边,用两个数组标记每一个集合的出度入度情况,得出入度和出度分别有几个集合为零,输出最大值。注意:调用tarjan函数的时候,用for循环,因为图可能不连通!还有当它本来就是一个连通分量的时候,特判一下。
例题:POJ 1236
Network of Schools

#include
#include
#include
#include
#include
#include
using namespace std;#define N 1010vector
edge[N];vector
belong[N];stack
s;int low[N];/*所属的强连通数组*/int dfn[N];/*访问的顺序*/bool instack[N];/*是否在栈内*/int n,m,u,v,cnt,cntb;/*n个顶点,m条边*/void Tarjan(int u)/*当前处于的节点*/{ ++cnt;/*计算访问到第几个点(时间戳)*/ dfn[u]=low[u]=cnt;/*访问的顺序(时间戳),low数组记录这个点所能回到的最早的时间戳*/ s.push(u); instack[u]=true; for(int i=0;i

转载地址:http://imsl.baihongyu.com/

你可能感兴趣的文章
斐波纳契数
查看>>
Java 十大排序算法
查看>>
SQL触发器
查看>>
建立第一个SpringBoot小列子(碰到的错误)
查看>>
整型关键字的散列映射
查看>>
多位水仙花数-python(出现运行超时?不妨用减法计算)
查看>>
地下迷宫探索(后两个测试点无法通过?这里有你想要的答案)
查看>>
城市间紧急救援(dijkstra算法)
查看>>
关键活动(注释超详细!!!)
查看>>
小白看完都会了!阿里云大师深入拆解Java虚拟机,看完这一篇你就懂了
查看>>
【IT之路】FAQ-Hibernate报错:表不存在
查看>>
【2020阿里云博客部署实战】如何远程连接和管理控制台基本介绍
查看>>
Java:class5 类的重载,final,static
查看>>
Linux中的C语言程序编译过程
查看>>
C程序举例:利用数组
查看>>
VBA之正则表达式(19)-- 相对引用转绝对引用
查看>>
巧用VBA统一数字单位
查看>>
Transpose实现数组行列转置的限制
查看>>
VBA中数组72变(随心所欲复制)
查看>>
[Golang]golang中自动锁的实现
查看>>