模板 - 图论 - 强连通分量 - Kosaraju算法
这个算法是自己实现的Kosaraju算法,附带一个缩点,其实缩点这个跟Kosaraju算法没有什么关系,应该其他的强连通分量算法计算出每个点所属的强连通分量之后也可以这样缩点。
算法复杂度:
Kosaraju算法:初始化,加边,两次dfs,复杂度O(n+m)
强连通分量缩点算法:遍历每个点每条边,复杂度O(n+m)
对边排序去重:复杂度O(n+mlogm)
注意:
1、最好先 Init() ,然后再 AddEdge()
2、维护缩点时点的性质对新点的影响在 dfs2() 中进行
3、维护缩点时边的性质对新点的影响在 Build() 中进行,特别注意缩点之后的自环
4、并不是每道题都需要原图反图,也并不是都需要对边进行去重
Kosaraju算法缩点的结果本身就是按拓扑序排列的。
namespace SCC {
int n;
vector<int> G[MAXN + 5], BG[MAXN + 5];
int c1[MAXN + 5], cntc1;
int c2[MAXN + 5], cntc2;
int s[MAXN + 5], cnts;
int n2;
vector<int> V2[MAXN + 5];
vector<int> G2[MAXN + 5], BG2[MAXN + 5];
void Init(int _n) {
n = _n;
cntc1 = 0, cntc2 = 0, cnts = 0;
for(int i = 1; i <= n; ++i) {
G[i].clear();
BG[i].clear();
c1[i] = 0;
c2[i] = 0;
s[i] = 0;
V2[i].clear();
G2[i].clear();
BG2[i].clear();
}
return;
}
void AddEdge(int u, int v) {
G[u].push_back(v);
BG[v].push_back(u);
return;
}
void dfs1(int u) {
c1[u] = cntc1;
for(auto &v : G[u]) {
if(!c1[v])
dfs1(v);
}
s[++cnts] = u;
}
void dfs2(int u) {
V2[cntc2].push_back(u);
c2[u] = cntc2;
for(auto &v : BG[u]) {
if(!c2[v])
dfs2(v);
}
return;
}
void Kosaraju() {
for(int i = 1; i <= n; ++i) {
if(!c1[i]) {
++cntc1;
dfs1(i);
}
}
for(int i = n; i >= 1; --i) {
if(!c2[s[i]]) {
++cntc2;
dfs2(s[i]);
}
}
return;
}
void Build() {
n2 = cntc2;
for(int i = 1; i <= n2; ++i) {
for(auto &u : V2[i]) {
for(auto &v : G[u]) {
if(c2[v] != i) {
G2[i].push_back(c2[v]);
BG2[c2[v]].push_back(i);
}
}
}
}
for(int i = 1; i <= n2; ++i) {
sort(G2[i].begin(), G2[i].end());
G2[i].erase(unique(G2[i].begin(), G2[i].end()), G2[i].end());
sort(BG2[i].begin(), BG2[i].end());
BG2[i].erase(unique(BG2[i].begin(), BG2[i].end()), BG2[i].end());
}
return;
}
void Solve() {
for(int i = 1; i <= n2; ++i) {
for(auto &u : V2[i]) {
//把原图的信息传递给新图;
}
}
//在新图上Solve;
return;
}
}
好像在不开O2的情况下这个vector版的比链式前向星版的费多了很多时间。
使用方法:
- Init,传入原图的点数。
- 使用AddEdge逐个加入有向边。
- 调用Kosaraju划分强连通分量(V2存储强连通缩点后的新点包含原图的哪些点,c2存储原图的点对应强连通缩点后的哪个新点)。
- 调用Build在强连通缩点之后的新点之间建立新边到G2,并排序去重。
- 在Solve中书写在DAG中求解的代码,例如先把原图的点的信息传递给强连通缩点后的新点,然后在DAG上dp(注意是使用G2)。
模板 - 图论 - 强连通分量 - Kosaraju算法的更多相关文章
- 有向图的强连通分量——kosaraju算法
一.前人种树 博客:Kosaraju算法解析: 求解图的强连通分量
- 图论-强连通分量-Tarjan算法
有关概念: 如果图中两个结点可以相互通达,则称两个结点强连通. 如果有向图G的每两个结点都强连通,称G是一个强连通图. 有向图的极大强连通子图(没有被其他强连通子图包含),称为强连通分量.(这个定义在 ...
- 图的强连通分量-Kosaraju算法
输入一个有向图,计算每个节点所在强连通分量的编号,输出强连通分量的个数 #include<iostream> #include<cstring> #include<vec ...
- NOIP专题复习3 图论-强连通分量
目录 一.知识概述 二.典型例题 1.[HAOI2006]受欢迎的牛 2.校园网络[[USACO]Network of Schools加强版] 三.算法分析 (一)Tarjan算法 (二)解决问题 四 ...
- 有向图强连通分量Tarjan算法
在https://www.byvoid.com/zhs/blog/scc-tarjan中关于Tarjan算法的描述非常好,转述如下: 首先解释几个概念: 有向图强连通分量:在有向图G中,如果两个顶点间 ...
- 【模板】强连通分量和tarjan算法
看了好久才终于明白了这个算法..复杂度是O(n+m). 我觉得这个算法不是很好理解,但是看懂了以后还是觉得听巧妙的. 下面给出模板代码和三组简单数据帮助理解. 代码如下: #include <s ...
- 模板 - 强连通分量 - Kosaraju
Kosaraju算法 O(n+m) vector<int> s; void dfs1(int u) { vis[u] = true; for (int v : g[u]) if (!vis ...
- 算法模板——Tarjan强连通分量
功能:输入一个N个点,M条单向边的有向图,求出此图全部的强连通分量 原理:tarjan算法(百度百科传送门),大致思想是时间戳与最近可追溯点 这个玩意不仅仅是求强连通分量那么简单,而且对于一个有环的有 ...
- 强连通分量-----Kosaraju
芝士: 有向图强连通分量在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connect ...
随机推荐
- C语言开发中常用英文缩写
BIOS(Basic Input Output System): 基本输入输出系统 reference: https://baike.baidu.com/item/bios/91424?fr=alad ...
- 【转载】C#中string.IsNullOrEmpty和string.IsNullOrWhiteSpace区别
在C#中判断字段是否为空或者Null的时候,我们一般会使用到string.IsNullOrEmpty和string.IsNullOrWhiteSpace方法,这两个方法在大部分情况下判断的结果是一致的 ...
- mySql入门-(二)
最近刚刚开始学习Mysql,然而学习MySql必经的一个过程就是SQL语句,只有按照文档从头开始学习SQL语句.学习的过程是痛苦的,但是学完的成果是甘甜的. SQL 语法 所有的 SQL 语句都以下列 ...
- Air for ANE:打包注意的地方
来源:http://blog.csdn.net/hero82748274/article/details/8631982 今天遇到了一个打包ANE 文件的问题,导致花费了几个小时查找,最后师弟的一句话 ...
- c#读写apk的 comment
写入: ZipFile zipFile = new ZipFile("C:\\Users\\Administrator\\Desktop\\2.apk"); zipFile.Beg ...
- php与ajax技术
web2.0的到来,ajax逐渐成为主流,什么是ajax,ajax的开发模式,优点,使用技术.(ajax概述,ajax使用的技术,需要注意的 问题,在PHP应用ajax技术的应用) 什么是ajax,a ...
- python+requests+excel+unittest+ddt接口自动化数据驱动并生成html报告(已弃用)
前言 1.环境准备: python3.6 requests xlrd openpyxl HTMLTestRunner_api 2.目前实现的功能: 封装requests请求方法 在excel填写接口请 ...
- Spark 宽窄依赖和stage的划分
窄依赖 父RDD和子RDD partition之间的关系是一对一的,或者父RDD一个partition只对应一个子RDD的partition情况下的父RDD和子RDD partition关系是多对一的 ...
- Linux kernel buffer ring
参考:What are the concepts of “kernel ring buffer”, “user level”, “log level”? Ring Buffer 原始问题 个人补充:r ...
- 【HICP Gauss】数据库 数据库高级语法(数据类型函数)-3
SQL高级语法:整型: integer 2(-31) ~2(31)-1 4字节 intger unsigned 2(0)~2(32)-1 4字节 bigint 2(-63)~2(63)-1 8字节 ...