这个算法是自己实现的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版的比链式前向星版的费多了很多时间。

使用方法:

  1. Init,传入原图的点数。
  2. 使用AddEdge逐个加入有向边
  3. 调用Kosaraju划分强连通分量(V2存储强连通缩点后的新点包含原图的哪些点,c2存储原图的点对应强连通缩点后的哪个新点)。
  4. 调用Build在强连通缩点之后的新点之间建立新边到G2,并排序去重。
  5. 在Solve中书写在DAG中求解的代码,例如先把原图的点的信息传递给强连通缩点后的新点,然后在DAG上dp(注意是使用G2)。

模板 - 图论 - 强连通分量 - Kosaraju算法的更多相关文章

  1. 有向图的强连通分量——kosaraju算法

    一.前人种树 博客:Kosaraju算法解析: 求解图的强连通分量

  2. 图论-强连通分量-Tarjan算法

    有关概念: 如果图中两个结点可以相互通达,则称两个结点强连通. 如果有向图G的每两个结点都强连通,称G是一个强连通图. 有向图的极大强连通子图(没有被其他强连通子图包含),称为强连通分量.(这个定义在 ...

  3. 图的强连通分量-Kosaraju算法

    输入一个有向图,计算每个节点所在强连通分量的编号,输出强连通分量的个数 #include<iostream> #include<cstring> #include<vec ...

  4. NOIP专题复习3 图论-强连通分量

    目录 一.知识概述 二.典型例题 1.[HAOI2006]受欢迎的牛 2.校园网络[[USACO]Network of Schools加强版] 三.算法分析 (一)Tarjan算法 (二)解决问题 四 ...

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

    在https://www.byvoid.com/zhs/blog/scc-tarjan中关于Tarjan算法的描述非常好,转述如下: 首先解释几个概念: 有向图强连通分量:在有向图G中,如果两个顶点间 ...

  6. 【模板】强连通分量和tarjan算法

    看了好久才终于明白了这个算法..复杂度是O(n+m). 我觉得这个算法不是很好理解,但是看懂了以后还是觉得听巧妙的. 下面给出模板代码和三组简单数据帮助理解. 代码如下: #include <s ...

  7. 模板 - 强连通分量 - Kosaraju

    Kosaraju算法 O(n+m) vector<int> s; void dfs1(int u) { vis[u] = true; for (int v : g[u]) if (!vis ...

  8. 算法模板——Tarjan强连通分量

    功能:输入一个N个点,M条单向边的有向图,求出此图全部的强连通分量 原理:tarjan算法(百度百科传送门),大致思想是时间戳与最近可追溯点 这个玩意不仅仅是求强连通分量那么简单,而且对于一个有环的有 ...

  9. 强连通分量-----Kosaraju

    芝士: 有向图强连通分量在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connect ...

随机推荐

  1. NIO开发Http服务器(2):项目结构

    最近学习了Java NIO技术,觉得不能再去写一些Hello World的学习demo了,而且也不想再像学习IO时那样编写一个控制台(或者带界面)聊天室.我们是做WEB开发的,整天围着tomcat.n ...

  2. Java调用WebService方法总结(7)--CXF调用WebService

    CXF = Celtix + XFire,继承了Celtix和XFire两大开源项目的精华,是一个开源的,全功能的,容易使用的WebService框架.文中所使用到的软件版本:Java 1.8.0_1 ...

  3. C#验证邮箱,电话,手机,数字,英文,日期,身份证,邮编,网址,IP类等常用函数封装

    #region 验证邮箱验证邮箱 /**//// <summary> /// 验证邮箱 /// </summary> /// <param name="sour ...

  4. 【JUC】7.CountDownLatch

    Latch:门闩.一种线程通信的方式:当程序不涉及同步,仅仅需要线程通信的时候,使用synchronize或者lock的线程通信等待唤醒机制,就显得太重了: 这时候,可以考虑使用信号量类:CountD ...

  5. 「8-27

    没有别的目的, 是最近发现一个小软件, 用起来感觉很不错, 所以想分享给大家. 首先这是一个 macOS 软件, 它的功能也很简单, 就是在菜单栏显示日期时间, 点按它可以显示日历, 没错, 简单到是 ...

  6. Ceph分布式存储部署过程

    前言: 环境介绍:此次部署系统为Cenots 7 MON.OSD 10.110.180.112 Admin MON.OSD 10.110.180.113 Node1 MON.OSD 10.110.18 ...

  7. 运维开发笔记整理-django日志配置

    运维开发笔记整理-django日志配置 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Django日志 Django使用python内建的logging模块打印日志,Pytho ...

  8. git 常见的命令和错误

  9. 软件测试_Loadrunner_性能测试_服务器资源监控

    使用Loadrunner进行Windows服务器性能监控 将装有Loadrunner的机器叫做监控端,被监控资源的服务器叫做被监控端 一.前置环境设置 1. 设置被监控端管理员账户可用:我的电脑右键- ...

  10. SQL进阶系列之0窗口函数

    窗口函数 What's 窗口函数? 窗口函数也称为OLAP(OnLine Analytical Processing)函数,目前MySQL还不支持. 窗口函数的语法 <窗口函数> OVER ...