有向图中,连通性比较好理解,如果两个顶点V和顶点W是可达的,可以称之为强连通的,即存在路径A→B,同时也存在一条有向路径B→A.从之前的有向环的判定过程中其实我们可以得到一个结论就是两个是强连通的当且仅当它们都在一个普通的有向环中。强连通将所有的顶点分为了不同的集合,每个集合都是由相互均为强连通性的顶点的最大子集组成的,我们将这些集合称之为强连通分量。

基础概念

一般来说技术服务于生活,如果将我们看到网页作为顶点,页面指向另外一个页面的超链接作为边,可以将数量庞大的网页分为不同的大小进行处理,作为软件工程师或者说码农,经常遇到的就是模块的封装,如果将模块作为顶点,模块之间的引用作为边,通过强连通图我们可以更好进行模块之间的调用关系考虑适时的解耦。如果通过平方级别的算法解决强连通分量,那么遇到大型有向图的过程我们就会有点力不从心。Kosaraju的算法(也称为Kosaraju-Sharir算法)是线性时间的算法来解决有向图中的连通性查询以及处理强连通分量的数量。

采用之前有向环中的图片:

API定义:

@interface KosarajuCC : NSObject

//记录顶点是否被标记
@property (strong,nonatomic) NSMutableArray *marked; @property (assign,nonatomic) NSInteger count;//连通的分量 @property (strong,nonatomic) NSMutableArray *ids;//顶点所在的连通分量的标识符 //连通分量递归初始化
-(instancetype)initWithGraph:(Digraph *)graph; -(void)depthSearch:(Digraph *)graph vertex:(NSInteger)vertex;
//判断两个顶点之间是否存在连通性
-(BOOL)stronglyConnected:(NSInteger)vertex otherVertex:(NSInteger)otherVertex; @end

算法实战

通过API的定义,如果对比之前之前无向图中的API,我们发现基本上没有变化,具体实现的过程中变化也很小,需要之前基于深度优先搜索的顶点排序,取出逆后序集合进行遍历即可,之后和无向图中一样进行递归判断存储在数组中。

@implementation KosarajuCC

#pragma mark  getter and setter
-(NSMutableArray *)marked{
if (!_marked) {
_marked=[[NSMutableArray alloc]initWithCapacity:1];
}
return _marked;
} -(NSMutableArray *)ids{
if (!_ids) {
_ids=[[NSMutableArray alloc]initWithCapacity:1];
}
return _ids;
} -(instancetype)initWithGraph:(Digraph *)graph{
self=[super init];
if (self) {
for (NSInteger i=0; i<graph.vertexs;i++) {
[self.marked addObject:[NSNull null]];
[self.ids addObject:[NSNull null]];
}
DepthFirstOrder *order=[[DepthFirstOrder alloc]initWithGraph:[graph reverse]];
//遍历图的顶点
for (NSInteger j=0; j<[order.reversePostStack count]; j++) {
NSInteger temp=[[order.reversePostStack objectAtIndex:j] integerValue];
if (![self isMarked:temp]) {
[self depthSearch:graph vertex:temp];
self.count++;
}
}
}
return self;
}
//博客园-FlyElephant:http://www.cnblogs.com/xiaofeixiang/
-(void)depthSearch:(Digraph *)graph vertex:(NSInteger)vertex{
self.marked[vertex]=[NSNumber numberWithBool:true];
//同一分量中顶点的赋值
self.ids[vertex]=[NSNumber numberWithInteger:self.count];
for (NSInteger i=0; i<[graph.adjDataSource[vertex] count]; i++) {
NSInteger temp=[[graph.adjDataSource[vertex] objectAtIndex:i] integerValue];
if (![self isMarked:temp]) {
[self depthSearch:graph vertex:temp];
}
}
} -(Boolean)isMarked:(NSInteger)vertex{
return self.marked[vertex]==[NSNull null]?false:[self.marked[vertex] boolValue];
} -(BOOL)stronglyConnected:(NSInteger)vertex otherVertex:(NSInteger)otherVertex{
return [self.ids[vertex] integerValue]==[self.ids[otherVertex] integerValue];
}
@end

测试代码:

        Digraph  *graph=[[Digraph alloc]initWithVertex:13];
[graph addEdges:4 endVertex:2];
[graph addEdges:2 endVertex:3];
[graph addEdges:3 endVertex:2];
[graph addEdges:6 endVertex:0];
[graph addEdges:0 endVertex:1];
[graph addEdges:2 endVertex:0];
[graph addEdges:11 endVertex:12];
[graph addEdges:12 endVertex:9];
[graph addEdges:9 endVertex:10];
[graph addEdges:9 endVertex:11];
[graph addEdges:8 endVertex:9];
[graph addEdges:10 endVertex:12];
[graph addEdges:11 endVertex:4];
[graph addEdges:4 endVertex:3];
[graph addEdges:3 endVertex:5];
[graph addEdges:7 endVertex:8];
[graph addEdges:8 endVertex:7];
[graph addEdges:5 endVertex:4];
[graph addEdges:0 endVertex:5];
[graph addEdges:6 endVertex:4];
[graph addEdges:6 endVertex:9];
[graph addEdges:7 endVertex:6];
KosarajuCC *graphCC=[[KosarajuCC alloc]initWithGraph:graph];
for (NSInteger i=0; i<graphCC.count; i++) {
NSMutableArray *dataSource=[[NSMutableArray alloc]initWithCapacity:1];
for (NSInteger j=0; j<graph.vertexs; j++) {
if ([graphCC.ids[j] integerValue]==i) {
[dataSource addObject:[NSNumber numberWithInteger:j]];
}
}
NSLog(@"分量%ld:%@",i,[dataSource componentsJoinedByString:@"--"]);
}
NSInteger vertex=0,otherVertex=1;
Boolean cc=[graphCC stronglyConnected:vertex otherVertex:otherVertex];
NSLog(@"节点%ld和节点%ld %@强连通的",vertex,otherVertex,cc==true?@"是":@"不是");
NSLog(@"技术交流群:%@",@"228407086");
NSLog(@"博客园-FlyElephant:http://www.cnblogs.com/xiaofeixiang");

测试结果:

算法-强连通分量和Kosaraju算法的更多相关文章

  1. 图论-求有向图的强连通分量(Kosaraju算法)

    求有向图的强连通分量     Kosaraju算法可以求出有向图中的强连通分量个数,并且对分属于不同强连通分量的点进行标记. (1) 第一次对图G进行DFS遍历,并在遍历过程中,记录每一个点的退出顺序 ...

  2. 强连通分量分解 Kosaraju算法 (poj 2186 Popular Cows)

    poj 2186 Popular Cows 题意: 有N头牛, 给出M对关系, 如(1,2)代表1欢迎2, 关系是单向的且能够传递, 即1欢迎2不代表2欢迎1, 可是假设2也欢迎3那么1也欢迎3. 求 ...

  3. Kosaraju算法、Tarjan算法分析及证明--强连通分量的线性算法

    一.背景介绍 强连通分量是有向图中的一个子图,在该子图中,所有的节点都可以沿着某条路径访问其他节点.强连通性是一种非常重要的等价抽象,因为它满足 自反性:顶点V和它本身是强连通的 对称性:如果顶点V和 ...

  4. 【强连通分量】tarjan算法及kosaraju算法+例题

    阅读前请确保自己知道强连通分量是什么,本文不做赘述. Tarjan算法 一.算法简介 Tarjan算法是一种由Robert Tarjan提出的求有向图强连通分量的时间复杂度为O(n)的算法. 首先我们 ...

  5. 有向图强连通分量的Tarjan算法

    有向图强连通分量的Tarjan算法 [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G ...

  6. 【转】有向图强连通分量的Tarjan算法

    原文地址:https://www.byvoid.com/blog/scc-tarjan/ [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly con ...

  7. 【转载】有向图强连通分量的Tarjan算法

    转载地址:https://www.byvoid.com/blog/scc-tarjan [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly conn ...

  8. 有向图强连通分量的Tarjan算法(转)

    [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极 ...

  9. 强连通分量的Tarjan算法

    资料参考 Tarjan算法寻找有向图的强连通分量 基于强联通的tarjan算法详解 有向图强连通分量的Tarjan算法 处理SCC(强连通分量问题)的Tarjan算法 强连通分量的三种算法分析 Tar ...

随机推荐

  1. 8.5 正睿暑期集训营 Day2

    目录 2018.8.5 正睿暑期集训营 Day2 总结 A.占领地区(前缀和) B.配对(组合) C 导数卷积(NTT) 考试代码 T1 T2 T3 2018.8.5 正睿暑期集训营 Day2 时间: ...

  2. bzoj4289 Tax

    Description 给出一个N个点M条边的无向图,经过一个点的代价是进入和离开这个点的两条边的边权的较大值,求从起点1到点N的最小代价.起点的代价是离开起点的边的边权,终点的代价是进入终点的边的边 ...

  3. 2016-2017 CT S03E06: Codeforces Trainings Season 3 Episode 6(8/13)

    2016-2017 CT S03E06: Codeforces Trainings Season 3 Episode 6 比赛连接: http://codeforces.com/gym/101124/ ...

  4. oracle创建透明网关出现的问题

    解决方案:创建HS_TRANSACTION_LOG表 DROP TABLE HS_TRANSACTION_LOG go CREATE TABLE HS_TRANSACTION_LOG( GLOBAL_ ...

  5. 在SpringMVC中使用@RequestBody注解处理json时,报出HTTP Status 415的解决方案

    Spring的@RequestBody非常牛x,可以将提交的json直接转换成POJO对象. 正好今天有这样的需求,使用一下,结果一直报415,十分头疼. HTTP 415 错误 – 不支持的媒体类型 ...

  6. AI 实验--v_JULY_v

    http://blog.csdn.net/v_JULY_v http://www.julyedu.com/

  7. java容器类---概述

    1.容器类关系图 虚线框表示接口. 实线框表示实体类. 粗线框表示最经常使用的实体类. 点线的箭头表示实现了这个接口. 实线箭头表示类能够制造箭头所指的那个类的对象. Java集合工具包位于Java. ...

  8. Android的学习之路(三)项目的启动过程和安装过程具体解释

    应用的安装和启动过程: 安装:第一步:java的编译器会把这个.java文件编译成.class文件           第二部:Android的SDK提供了一个dx工具,这个工具把.class文件转义 ...

  9. DXT 图片压缩(DXTC/DirectX Texture Compression Overview)

    这两天在写 DDS 格式的解码程序.DDS 是微软为 DirectX 开发的一种图片格式,MSDN 上可以查到其文件格式说明: http://msdn2.microsoft.com/en-us/lib ...

  10. cvCreateStumpClassifier

    CV_BOOST_IMPL CvClassifier* cvCreateStumpClassifier( CvMat* trainData, //训练样本的数据,包含图像大小.数量,类别,权重等 in ...