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

强连通分量

时间:2018-01-20 19:51:14      阅读:178      评论:0      收藏:0      [点我收藏+]

标签:tracking   tail   article   顺序   add   end   src   推断   blog   

有向图的强连通分量

在有向图中,u可达v不一定意味v可达到u,相互可达的节点则属于同一个强连通分量。



某节点的传递闭包为该节点所处的强连通分量和它所有后代所处的强连通分量的节点。

若有向图的所有节点同属于一个强连通分量,则称该有向图为强连通图。

在有向图中。若某子图中的任一对节点都互为可达,则该子图称为有向图的强连通分量。

计算有向图中强连通分量的方法例如以下:将有向图G中每条边的方向取反,得到图G的一个转置GT,G和GT中的强连通分量同样。将每一个强连通分量缩成一个节点,就能够得到一个无环有向图Gscc。

技术分享图片? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??技术分享图片

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??技术分享图片

1、Procedure Kosaraju(G);
{调用dfs(G)计算出每一个节点的f[u];
计算图G的转置GT;
调用dfs(GT),在主循环中依照f[u]递减的顺序依次对每一个未訪问点执行dfs过程,则得到的每棵dfs树恰好相应于一个强连通分量;
}

技术分享图片? ? ? ? ? ? ? ? ? ? ? ? ? ?技术分享图片

V

0

1

2

3

4

5

6

7

8

9

10

11

12

d

1

17

2

3

4

5

7

8

9

19

21

23

20

f

16

18

15

14

13

6

12

11

10

26

22

24

25










技术分享图片? ? ? ??技术分享图片

f

26

25

24

22

18

16

15

14

13

12

11

10

6

v

9

12

11

10

1

0

2

3

4

6

7

8

5

0

0

0

0

1

2

2

2

2

2

3

3

2



模板:
const maxn=100;
var ? ? ? ?//map[x,i] 记录与点x邻接的第i个点的编号 ? map[x,0]记录和x邻接的点的个数
? map,map1:array[1..maxn,0..maxn]of integer; ?
? visit:array[1..maxn]of boolean; ? //记录该点是否被遍历过
? list:array[1..maxn]of integer; ? ? ?//记录n个点的遍历次序
? n,m,pos,scc:integer; ? ? ? ? ? ? ? ? ?//pos记录进入list数组的点的个数 ?scc记录强连通分量的个数?

procedure init;
var i,x,y:integer;
begin
? readln(n,m);
? for i:=1 to m do
? begin
? ? readln(x,y);
? ? inc(map[x,0]);
? ? map[x,map[x,0]]:=y; ??
? ? inc(map1[y,0]);
? ? map1[y,map1[y,0]]:=x;?
end;
end;

procedure dfs(p:integer);
var i,j,k:integer;
begin
? visit[p]:=true; k:=map[p,0];
? for i:=1 to k do
? begin
? ? j:=map[p,i];
? ? if not visit[j] then dfs(j);
? end;
? inc(pos); ?list[pos]:=p;
end;

procedure dfs1(p:integer);
var i,j,k:integer;
begin
? visit[p]:=true;
? k:=map1[p,0];
? for i:=1 to k do
? begin
? ? j:=map1[p,i];
? ? if not visit[j] then dfs1(j);
? end;
end;

procedure kosaraju;
var i,j,k:integer;
begin
fillchar(visit,sizeof(visit),false);
? for i:=1 to n do if not visit[i] then dfs(i);?
? fillchar(visit,sizeof(visit),false); ?scc:=0;
? for i:=pos downto 1 do ?//每深搜完一次,表示找完一个强连通图,增加scc
? ? if not visit[list[i]] then begin dfs1(list[i]); inc(scc); end;
end;

begin
? init;
? pos:=0;
? kosaraju;
? writeln(scc);
end.


2、Tarjan算法

Tarjan算法是基于对图深度优先搜索的算法,每一个强连通分量为搜索树中的一棵子树。搜索时,把当前搜索树中未处理的节点增加一个堆栈。回溯时能够推断栈顶到栈中的节点是否为一个强连通分量。

技术分享图片

技术分享图片

算法流程演示:

1.从节点1開始DFS。把遍历到的节点增加栈中。搜索到节点u=6时,DFN[6]=LOW[6],找到了一个强连通分量。退栈到u=v为止,{6}为一个强连通分量。

技术分享图片

2.返回节点5,发现DFN[5]=LOW[5],退栈后{5}为一个强连通分量。

技术分享图片

3.返回节点3,继续搜索到节点4。把4增加堆栈。发现节点4向节点1有后向边,节点1还在栈中,所以LOW[4]=1。

节点6已经出栈,(4,6)是横叉边。返回3,(3,4)为树枝边,所以LOW[3]=LOW[4]=1。

技术分享图片

4.继续回到节点1。最后訪问节点2。訪问边(2,4),4还在栈中。所以LOW[2]=DFN[4]=5。

返回1后,发现DFN[1]=LOW[1]。把栈中节点所有取出,组成一个连通分量{1,3,4,2}。

技术分享图片

至此,算法结束。经过该算法,求出了图中所有的三个强连通分量{1,3,4,2},{5},{6}。
能够发现。执行Tarjan算法的过程中,每一个顶点都被訪问了一次,且仅仅进出了一次堆栈,每条边也仅仅被訪问了一次,所以该算法的时间复杂度为O(N+M)。

模板:

var
? a:array [1..1000,1..1000] of longint;
? low,dfn,c:array [1..1000] of longint;
? v,f,ff:array [1..1000] of boolean;
? i,j,m,n,x,y,d,ans:longint;


function min(x,y:longint):longint;
begin
? if x>y then
? exit(y);
? exit(x);
end;


procedure tarjan(x:longint);
var
? i:longint;
begin
? inc(d);
? low[x]:=d;
? dfn[x]:=d;
? f[x]:=true;
? for i:=1 to c[x] do
? begin
? ? if not v[a[x,i]] then
? ? begin
? ? ? v[a[x,i]]:=true;
? ? ? tarjan(a[x,i]);
? ? ? low[x]:=min(low[x],low[a[x,i]]);
? ? end else
? ? begin
? ? ? if f[a[x,i]] then
? ? ? low[x]:=min(low[x],dfn[a[x,i]]);
? ? end;
? end;
? if dfn[x]=low[x] then
? inc(ans);
end;


begin
? readln(n);
? for i:=1 to n do
? begin
? ? read(x);
? ? while x<>0 do
? ? begin
? ? ? inc(c[i]);
? ? ? a[i,c[i]]:=x;
? ? ? read(x);
? ? end;
? end;
? for i:=1 to n do
? if not v[i] then
? begin
? ? v[i]:=true;
? ? tarjan(i);
? end;
? writeln(ans);
end.


有几道习题:

1.http://blog.csdn.net/boyxiejunboy/article/details/46891399

2.http://blog.csdn.net/boyxiejunboy/article/details/46891417

3.http://blog.csdn.net/boyxiejunboy/article/details/46891815


具体详见:http://download.csdn.net/detail/boyxiejunboy/8908487(更加具体哦)







强连通分量

标签:tracking   tail   article   顺序   add   end   src   推断   blog   

原文地址:https://www.cnblogs.com/zhchoutai/p/8321637.html

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