有向图中,连通性比较好理解,如果两个顶点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. android弹出对话框

    我们在平时做开发的时候,免不了会用到各种各样的对话框,相信有过其他平台开发经验的朋友都会知道,大部分的平台都只提供了几个最简单的实现,如果我们想实现自己特定需求的对话框,大家可能首先会想到,通过继承等 ...

  2. 每日踩坑 2018-12-25 【Unable to convert MySQL date/time value to System.DateTime】异常

    之前的公司一直是用 ORM ,所以底层的事情完全不用在意, 到了这家全是似乎全是 SQL 硬编码 所以也有机会重新去补补以前也没怎么写过的基本 ADO. 不过这两天总有自己写个简易ORM的想法在蠢蠢欲 ...

  3. BZOJ.4456.[ZJOI2016]旅行者(分治 Dijkstra)

    题目链接 \(Description\) 给定\(n\times m\)的带边权网格图.\(Q\)次询问从点\((x_i,y_i)\)到点\((x_j,y_j)\)的最短路. \(n\times m\ ...

  4. Jenkins持续集成环境, 如何自定义 maven repositories

    假设自定义的仓库路径为“/opt/repository”,那么在“系统管理-系统设置”中,修改“全局MAVEN_OPTS”的值为如下的内容: -Dmaven.repo.local=/opt/repos ...

  5. hdu 5828 Rikka with Sequence 线段树

    Rikka with Sequence 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5828 Description As we know, Rik ...

  6. WAP 2.0开发XHTML MP语法及常用功能

    XHTML Mobile Profile 的基本结构 <?xml version="1.0" encoding="utf-8"?> <!DOC ...

  7. LPC43xx SGPIO I2C Implementation

    I²C SGPIO Configuration SGPIO is a hardware feature of LPC4300 series. There are 16 SGPIO pins calle ...

  8. C# webrequest 抓取数据时,多个域Cookie的问题

    最近研究了下如何抓取为知笔记的内容,在抓取笔记里的图片内容时,老是提示403错误,用Chorme的开发者工具看了下: 这里的Cookie来自两个域,估计为知那边是验证了token(登录后才能获取到to ...

  9. Golang 版本发布 与 TIOBE 排名

    2016年国庆节(10月1日)开始接触 Go 语言,记录一下它的 版本发布 与 TIOBE 排名: Golang 排行榜 月份 版本 排名 备注 2012.03 1.0             201 ...

  10. .net项目中使用Quartz

    (1)在web.config中进行相关配置 <configSections> <section name="quartz" type="System.C ...