简介
首先需要复习一下图论的一系列知识,理解有向图的强连通分量的定义,求解有向图的强连通分量算法有很多,例如Kosaraju,Gabow和Tarjan算法,其中Gabow和Tarjan算法时间复杂度要优于Kosaraju。在这里我们使用Tarjan求解SCC。
在此之前你可以对SCC有个直观的认识,放图:
然后看一篇浅显的说明性的文字,了解这个算法的思想:
http://www.voidcn.com/blog/wr132/article/p-4891712.html
然后我们需要贴一篇经典的文章讲解,传送门如下:
https://www.byvoid.com/blog/scc-tarjan/
理解:
核心思想:一个强连通分量中任意两个节点一定是互相可达的,那么这个强连通分量的从i到j的路径构成一个环(when i=j),因此我们的核心思想就是寻找环。
1. DFN[i]数组存储第i个节点的访问时间time,LOW[i]数组存储当前第i个节点能够直接或者间接访问到的最早的节点的时序time。
2. 本算法基于DFS,当遍历到第i个节点的时候,递归结束的条件就是考虑第i个节点的DFN值和LOW是否相等,通俗点说就是这个点能找到的最小时间的点是自身,即从i出发可以回到i,那么i后面遍历到的点包括i在内构成了一个有向图的强连通分量。
3. 其次我们考虑递归遍历的时候,第i个节点的下一个节点i+1如果遍历完毕,我们考虑i+1的LOW值,取i和i+1的LOW值中小的;如果i+1在栈中,说明之前遍历过,如果DFN值小,说明之前遍历过,从当前i到i+1很可能构成环,取之。
下面用一道CCF的题目应用一下SCC算法。
问题描述
某国有n个城市,为了使得城市间的交通更便利,该国国王打算在城市之间修一些高速公路,由于经费限制,国王打算第一阶段先在部分城市之间修一些单向的高速公路。
现在,大臣们帮国王拟了一个修高速公路的计划。看了计划后,国王发现,有些城市之间可以通过高速公路直接(不经过其他城市)或间接(经过一个或多个其他城市)到达,而有的却不能。如果城市A可以通过高速公路到达城市B,而且城市B也可以通过高速公路到达城市A,则这两个城市被称为便利城市对。
国王想知道,在大臣们给他的计划中,有多少个便利城市对。
输入格式
输入的第一行包含两个整数n, m,分别表示城市和单向高速公路的数量。
接下来m行,每行两个整数a, b,表示城市a有一条单向的高速公路连向城市b。
输出格式
输出一行,包含一个整数,表示便利城市对的数量。
样例输入
5 5
1 2
2 3
3 4
4 2
3 5
样例输出
3
题解
- 本题思路在于求出SCC,每个SCC内部的任意两个节点都是相互可达的,我们使用 C