算法-强连通分量和Kosaraju算法
有向图中,连通性比较好理解,如果两个顶点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算法的更多相关文章
- 图论-求有向图的强连通分量(Kosaraju算法)
求有向图的强连通分量 Kosaraju算法可以求出有向图中的强连通分量个数,并且对分属于不同强连通分量的点进行标记. (1) 第一次对图G进行DFS遍历,并在遍历过程中,记录每一个点的退出顺序 ...
- 强连通分量分解 Kosaraju算法 (poj 2186 Popular Cows)
poj 2186 Popular Cows 题意: 有N头牛, 给出M对关系, 如(1,2)代表1欢迎2, 关系是单向的且能够传递, 即1欢迎2不代表2欢迎1, 可是假设2也欢迎3那么1也欢迎3. 求 ...
- Kosaraju算法、Tarjan算法分析及证明--强连通分量的线性算法
一.背景介绍 强连通分量是有向图中的一个子图,在该子图中,所有的节点都可以沿着某条路径访问其他节点.强连通性是一种非常重要的等价抽象,因为它满足 自反性:顶点V和它本身是强连通的 对称性:如果顶点V和 ...
- 【强连通分量】tarjan算法及kosaraju算法+例题
阅读前请确保自己知道强连通分量是什么,本文不做赘述. Tarjan算法 一.算法简介 Tarjan算法是一种由Robert Tarjan提出的求有向图强连通分量的时间复杂度为O(n)的算法. 首先我们 ...
- 有向图强连通分量的Tarjan算法
有向图强连通分量的Tarjan算法 [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G ...
- 【转】有向图强连通分量的Tarjan算法
原文地址:https://www.byvoid.com/blog/scc-tarjan/ [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly con ...
- 【转载】有向图强连通分量的Tarjan算法
转载地址:https://www.byvoid.com/blog/scc-tarjan [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly conn ...
- 有向图强连通分量的Tarjan算法(转)
[有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极 ...
- 强连通分量的Tarjan算法
资料参考 Tarjan算法寻找有向图的强连通分量 基于强联通的tarjan算法详解 有向图强连通分量的Tarjan算法 处理SCC(强连通分量问题)的Tarjan算法 强连通分量的三种算法分析 Tar ...
随机推荐
- Xamarin iOS教程之申请付费开发者账号下载证书
Xamarin iOS教程之申请付费开发者账号下载证书 Xamarin iOS使用真机测试应用程序 在讲解iOS Simulator时,已经提到了虽然iOS Simulator可以模仿真实的设备,但是 ...
- https建立通讯过程及运行机制 [转]
ssl与tls: SSL:(Secure Socket Layer,安全套接字层),为Netscape所研发,用以保障在Internet上数据传输之安全,利用数据加密(Encryption)技术,可确 ...
- 在vi 按了Ctrl s 之后..
习惯了在windows下写程序,也习惯了按ctrl+s 保存代码,在用vi的时候,也习惯性的按了ctrl+s 然后vi终端就像卡住了一样. 原来: ctrl+s 终止屏幕输出(即停止回显),你敲的依然 ...
- Centos7 安装 ActiveMQ 5.15.1
环境 [root@node1 ~]# cat /etc/redhat-release CentOS Linux release (Core) [root@node1 ~]# uname -r -.el ...
- Codeforces Round #368 (Div. 2) A. Brain's Photos 水题
A. Brain's Photos 题目连接: http://www.codeforces.com/contest/707/problem/A Description Small, but very ...
- 注册Goole 账户 成功注册
注册谷歌邮箱等Google帐号时提示:此电话号码无法用于进行验证怎么办? 相信很多网友在注册Google帐号的时候需要手机号码验证,比如在遇到过注册Google Gmail到最后一步“验证您的帐号” ...
- 利用最新的CentOS7.5,hadoop3.1,spark2.3.2搭建spark集群
1. 桥接模式,静态ip上外网:vi /etc/sysconfig/network-scripts/ifcfg-ens33 TYPE=EthernetPROXY_METHOD=noneBROWSER_ ...
- windows下用nginx配置https服务器
1.安装nginx 先到nginx官网下在nginx http://nginx.org/en/download.html 将下载好的文件解压出来修改文件名为 nginx ,然后拷贝到C盘下,目录如下: ...
- 在windows server 2008 R2 64bit上面配置PI OPC Server的DCOM
今天想配置PI OPC SERVER的DCOM设置,但是发现在“运行dcomcnfg->组件服务-计算机-我的电脑-DCOM设置”中找不到PI OSI DA Server.如下图所示 这是以前从 ...
- 分享下使用 svn,测试服务器代码自动更新、线上服务器代码手动更新的配置经验
分享下使用 svn,测试服务器代码自动更新.线上服务器代码手动更新的配置经验 利用SVN的POST-COMMIT钩子自动部署代码 Linux SVN 命令详解 Linux SVN 命令详解2 使用sv ...