算法-强连通分量和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 进度条 进度条可以看到每一项任务现在的状态.例如在下载的应用程序中有进度条,用户可以很方便的看到当前程序下载了多少,还剩下多少.Q ...
- Luogu2482 [SDOI2010]猪国杀 ---- 模拟
Luogu2482 [SDOI2010]猪国杀 题意 ...... https://www.luogu.org/problemnew/show/P2482 总结 首先说一下代码的构思: 首先确定了所有 ...
- Bzoj4818:生成函数 快速幂
转来的题面:首先这题显然补集转化,就是用全部方案减去不含任何质数的方案.然后怎么做呢?考虑m比较小,我们能大力把<=m的质数全都筛出来.发现n很大,要么倍增要么快速幂......发现p相当小,所 ...
- luoguP4389 付公主的背包 多项式exp
%%%dkw 话说这是个论文题来着... 考虑生成函数\(OGF\) 对于价值为\(v\)的物品,由于有\(10^5\)的件数,可以看做无限个 那么,其生成函数为\(x^0 + x^{v} + x^{ ...
- 深刻领悟javascript中的exec与match方法之异同
阅读本文之前,请先看下面一道题: 题目17:Read the following javascript code: var someText="web2.0 .net2.0"; ...
- BZOJ3009 : 集合
取一棵生成森林,根据题目限制可得,与一个点相连的多余的边数是$O(\sqrt{m})$级别的. 对于树边,每个点维护3棵权值线段树,依次保存它的儿子里各个集合的边. 再开3*3个分块数组,记录多余边以 ...
- 使用GSON和泛型解析约定格式的JSON串(转)
时间紧张,先记一笔,后续优化与完善. 解决的问题: 使用GSON和泛型解析约定格式的JSON串. 背景介绍: 1.使用GSON来进行JSON串与java代码的互相转换. 2.JSON的格式如下三种: ...
- 报错:Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
在保存数据的时候报这个错误,知道是验证错误,但到底是哪个属性验证错误呢? →打断点,运行,观察程序出错的地方→在出错的部分添加try...catch语句块→添加监视,输入((System.Data.E ...
- android模拟器修改时间
我们看右上角的模拟器的时间,是不是和我们现在时间不同步呢 点击主菜单之后,我们找到下边的设置的按钮 下边找到时间和日期, 怎么把页面修改中文, 可以看(安卓模拟器怎么修改语言)的经验 ...
- SQLCE使用
Windows Phone的本地数据库SQL Server CE是7.1版本即芒果更新的新特性,所以你要在应用程序中使用SQL Server CE数据库必须使用Windows Phone 7.1的AP ...