强连通分量(SCC)Kosaraju算法学习笔记

一、深度优先生成树

在对无向图或有向图G进行从顶点v出发的深度优先搜索时,由v引向未被访问(标记)的顶点的边,构成以v为根的一棵树,这棵树被称为深度优先生成树(DFST)。

始点v称为树根、树上的每条边称为树边。

对G的完整地深度优先搜索,可能把G的顶点分划在若干棵DFST上,这若干棵DFST合在一起称为图G的深度优先生成森林(DFST)。  



二、有向图的边分类

1.祖先点和子孙点

在G的DFST中,若顶点x在从根导顶点y的路上,则称x是y的祖先,y是x的子孙;根是树中所有其它顶点的祖先;当x¹y时,称x是y的真祖先,y是x的真子孙。

2.树边――在G的DFST上的边。 

3.后向边――若G的一条非树边e放到其DFST上后,它是从某个顶点指向该顶点的祖先的连边,则把它称为后向边。

4.前向边――从某顶点指向该顶点的子孙点的连边。

5.横跨边(横向边)――若边的两顶点无祖先、子孙关系,则把它称为横跨边。  



三、深度优先数与后序数

1、深度优先数:顶点v的深度优先数dfnumber(v)为:在DFS中,顶点v被访问的次序计数值。

应用:

1)w是v的子孙Ûdfnumber(v)<dfnumber(w)≤dfnumber(v)+v的子孙数。

2)xy是后向边Ûdfnumber(x)>dfnumber(y),且y是x的祖先。

3)xy是前向边Ûdfnumber(x)<dfnumber(y),且y是x的子孙。

4)xy是横向边Ûdfnumber(x)>dfnumber(y),且x、y没有祖先、子孙关系。


2、后序数:对G做DFS时,各顶点退出DFS(由该点返退到其祖先点时)的次序计数。 



四、反图

将有向图G的所有边反向后得到的图。记为Gr。



五、有向图的连通性

1)弱连通――若对G的任意两顶点vi、vj,从vi到vj或从vj到vi有一条路,则称G是弱连通的。
2)强连通――若对G的任意两顶点vi、vj,从vi到vj且从vj到vi均有一条路,则称G是强连通的。
3)强连通分支(强分支)――G的极大强连通子图

  在G的顶点集V上定义一个关系R:


六、Kosaraju算法的基本思想

首先明确:图G的反图Gr与图G的连通分量是一样的。

从图中某个顶点开始进行遍历得到的DFS树可能包含整个图,即可能将所有SCC混在一起。就是说,在未知G的连通性的前提下,DFS的始点选取,对找其强分支是有制约的。能否把始点定下来,从此点开始,通过DFS把G的强分支都找出来呢?

设图G为SC-->SC1,其中SC、SC1为连通分量,SC到SC1有一条边相连。

分析知:不管是选SC1上的点还是选SC2上的点作为始点进行DFS,最后退出DFS的点(后序数最大)一定在SC1上。若选最后退出DFS的点为始点并对Gr也进行一次DFS,则可以将Gr的强分支找到,从而也就确定了G的强分支。

由此得到以下算法:

对有向图G做DFS,求出每个顶点的后序数

2.求G的反图Gr

3.选其后序数最大的顶点作为起始点对Gr进行DFS;当该始点的选取不能访到Gr的所有顶点时,再在剩余的顶点中选其后序数较大的顶点为始点,继续对Gr进行DFS,直到访问完Gr的所有顶点为止。

4.把Gr的每一棵DFST上的顶点及其在G中的关联边作为G的一个强分支。


模板(vector邻接表实现):

#define maxn 505
vector<int>G[maxn],G2[maxn];//G的逆图保存在G2中。
vector<int>S;
int vis[maxn],sccno[maxn],scc_cnt;

void dfs1(int u){
    if(vis[u]) return;
    vis[u]=1;
    for(int i=0;i<G[u].size();++i) dfs1(G[u][i]);
    S.push_back(u);//按后序数由小到大存放顶点。
}

void dfs2(int u){
    if(sccno[u]) return;
    sccno[u]=scc_cnt;
    for(int i=0;i<G2[u].size();++i) dfs2(G2[u][i]);
}

void find_scc(int n){
    scc_cnt=0;
    S.clear();
    memset(sccno,0,sizeof(sccno));
    memset(vis,0,sizeof(vis));
    for(int i=0;i<n;++i) dfs1(i);
    for(int i=n-1;i>=0;--i)
    if(!sccno[S[i]]) {++scc_cnt;dfs2(S[i]);}
}


算法时间复杂度以及正确性:略。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值