kosaraju求强连通分量
在了解kosaraju算法之前我们先了解一下什么是强连通分量,在有向图中如果两个定点vi,ui存在一条路劲从vi到达ui且也存在一条路劲从ui到达vi那么由ui和vi这两个点构成的图成为强连通图,简洁一点就是存在两个或两个点以它们之间可以相互可达由这些点构成的图就称之为强连通图它们的存在形式可以如下

当然一个点也是一个强连通分量,它们都满足所有点之间都可以互相可达。
以上就是对强连通分量的介绍接下来对kosaraju算法思路进行分析。
我们将对下面这个图进行对kosaraju算法进行解析:
我们可以发现此图存在两个强联通分量它们分别是,强连通分量A:1,3,2; 强连通分量B:5,4,6。
kosaraju的主要思想就是图进行两边dfs但是第二遍dfs的图必须是与原图相反的图,然后将第一遍的dfs比例的顺序用栈存起来然后再用栈内的元素对原图的反向图进行遍历最后就可以求得强连通分量。
Q:为什么要跑两边dfs?
A:kosaraju主要还是介于dfs遍历原理上,对于上图的dfs遍历我们假设以点1作为起点所以我们可以的的dfs遍历序为下图中绿色的回溯的点push进入栈中
所以栈内的值为1,3,5,4,6,2。

当以点1为起点进行dfs搜索我们会从点1搜到点6并不能确定强连通分量的元素但是当我们将原图反向建图再跑dfs的时候我们会发现每个强连通分量都可以分开了
为什么?我们将用图解释:
原图反图的建立,我们可以发下当我们把原图反向建立时,我们可以发现由3-->5这条边变成了5-->3这条边,当我们再以点1为起点进行dfs时我们可以发现与之前不同点1不能遍历完全部节点

因此第二遍dfs跑原图的反图时我们就将两个强连通分量给分开了,正好在第一遍dfs我们就将正图的dfs序存入栈中,那我们在第二遍dfs的时候我们只需要将栈中的元素取出跑一边反向图即可
求得强连通分量。
上面这个图我们可以手推得到,强连通分量1: 1,3,2; 强连通分量2: 5,4,6。
代码:
第一遍dfs跑正图将图的dfs序存入栈中:
void dfs1(int x)
{
if(vis[x]) return;
vis[x]=true;
for(int i=;i<vt[x].size();i++)
dfs1(vt[x][i]);
z.push(x);
return;
}
第二遍dfs跑一边反着的原图:
void dfs2(int x)
{
for(int i=;i<rvt[x].size();i++)
{
if(vis[rvt[x][i]]) continue;
vis[rvt[x][i]]=true;
dfs2(rvt[x][i]);
out<<rvt[x][i]<<" ";
}
return;
}
void scc_find()
{
memset(vis,false,sizeof(vis));//跑第二遍dfs的时候vis标记数组一定要初始化为false
while(!z.empty())//对栈内的元素进行dfs寻找强连通分量
{
int t=z.top();
z.pop();
if(vis[t]) continue;
vis[t]=true;
scc++;
out<<"group:"<<t<<" ";
dfs2(t);
out<<endl;
}
return;
}
完整代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <stack>
#include <vector>
using namespace std;
#define in cin
#define out cout
typedef long long insert;
const int N=2e5+;
stack<int> z;
vector<int> vt[N];
vector<int> rvt[N];
insert n,m,x,y,scc;
bool vis[N];
void inital_value()
{
for(int i=;i<=m;i++)
{
in>>x>>y;
vt[x].push_back(y);
rvt[y].push_back(x);//反向存图
}
return;
}
void dfs1(int x)
{
if(vis[x]) return;
vis[x]=true;
for(int i=;i<vt[x].size();i++)
dfs1(vt[x][i]);
z.push(x);
return;
}
void dfs2(int x)
{
for(int i=;i<rvt[x].size();i++)
{
if(vis[rvt[x][i]]) continue;
vis[rvt[x][i]]=true;
dfs2(rvt[x][i]);
out<<rvt[x][i]<<" ";
}
return;
}
void scc_find()
{
memset(vis,false,sizeof(vis));//跑第二遍dfs的时候vis标记数组一定要初始化为false
while(!z.empty())//对栈内的元素进行dfs寻找强连通分量
{
int t=z.top();
z.pop();
if(vis[t]) continue;
vis[t]=true;
scc++;
out<<"group:"<<t<<" ";
dfs2(t);
out<<endl;
}
return;
}
int main()
{
in>>n>>m;
inital_value();
for(int i=;i<=n;i++)
{
if(vis[i]) continue;
dfs1(i);
}
scc_find();
out<<"强连通分量总数"<<endl;
out<<scc<<endl;
return ;
}
kosaraju求强连通分量的更多相关文章
- kosaraju算法求强连通分量
什么是强连通分量?在这之前先定义一个强连通性(strong connectivity)的概念:有向图中,如果一个顶点s到t有一条路径,t到s也有一条路径,即s与t互相可达,那么我们说s与t是强连通的. ...
- UESTC 901 方老师抢银行 --Tarjan求强连通分量
思路:如果出现了一个强连通分量,那么走到这个点时一定会在强连通分量里的点全部走一遍,这样才能更大.所以我们首先用Tarjan跑一遍求出所有强连通分量,然后将强连通分量缩成点(用到栈)然后就变成了一个D ...
- poj 2186 tarjan求强连通分量
蕾姐讲过的例题..玩了两天后才想起来做 貌似省赛之后确实变得好懒了...再努力两天就可以去北京玩了! 顺便借这个题记录一下求强连通分量的算法 1 只需要一次dfs 依靠stack来实现的tarjan算 ...
- 求强连通分量模板(tarjan算法)
关于如何求强连通分量的知识请戳 https://www.byvoid.com/blog/scc-tarjan/ void DFS(int x) { dfn[x]=lowlink[x]=++dfn_cl ...
- [Uva247][Tarjan求强连通分量][Calling Circles]
题目大意: 例如:A跟B打电话,B跟C打电话,C跟A打电话..D跟E打电话,E跟D不打电话.则A,B,C属于同一个电话圈,D,E分别属于一个电话圈,问有多少个电话圈. 分析 就是裸的求强连通分量,直接 ...
- tarjan求强连通分量+缩点+割点以及一些证明
“tarjan陪伴强联通分量 生成树完成后思路才闪光 欧拉跑过的七桥古塘 让你 心驰神往”----<膜你抄> 自从听完这首歌,我就对tarjan开始心驰神往了,不过由于之前水平不足,一 ...
- Tarjan求强连通分量,缩点,割点
Tarjan算法是由美国著名计算机专家发明的,其主要特点就是可以求强连通分量和缩点·割点. 而强联通分量便是在一个图中如果有一个子图,且这个子图中所有的点都可以相互到达,这个子图便是一个强连通分量,并 ...
- tarjan求强连通分量+缩点+割点/割桥(点双/边双)以及一些证明
“tarjan陪伴强联通分量 生成树完成后思路才闪光 欧拉跑过的七桥古塘 让你 心驰神往”----<膜你抄> 自从听完这首歌,我就对tarjan开始心驰神往了,不过由于之前水平不足,一 ...
- HDU 1827 Summer Holiday(tarjan求强连通分量+缩点构成新图+统计入度+一点贪心思)经典缩点入门题
Summer Holiday Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
随机推荐
- 100个常用的linux命令(转)
来源:JavaRanger – javaranger.com http://www.javaranger.com/archives/907 1,echo “aa” > test.txt 和 ...
- App 运行后屏幕顶部和底部各留黑边问题 - iOS
App 启动后屏幕的顶部和底部各产生一条黑边,App 的内容会被压缩在两个黑条内显示,比例失调的情况. 初步判断是启动页资源图片适配问题. 首先,查看工程 project => General ...
- iOS11、iPhone X、Xcode9 适配指南
更新iOS11后,发现有些地方需要做适配,整理后按照优先级分为以下三类: 1.单纯升级iOS11后造成的变化: 2.Xcode9 打包后造成的变化: 3.iPhoneX的适配 一.单纯升级iOS11后 ...
- OC - 时间日期类NSDate
OC - 时间日期类NSDate //NSDate 时间日期类 NSDate 二进制数据流 { //1.获取当前时间 零时区的时间 //显示的是格林尼治的时间: 年-月-日 时:分:秒:+时区 NSD ...
- RN如何固定底部的按钮
如上图的底部新增按钮,要是放在web里那是相当简单,直接是用固定定位就行,但是在RN里是没有固定定位可言的. 方案一: 采用绝对定位,相对于最外层的定位在底部位置.(在部分安卓机上有问题,动态计算的高 ...
- 20181030noip模拟赛T1
YY的矩阵 YY有一个大矩阵(N*M), 矩阵的每个格子里都有一个整数权值W[i,j](1<=i<=M,1<=j<=N) 对于这个矩阵YY会有P次询问,每次询问这个大矩阵的一个 ...
- golang刷Leetcode系列 --- 加1
加一 给定一个非负整数组成的非空数组,在该数的基础上加一,返回一个新的数组. 最高位数字存放在数组的首位, 数组中每个元素只存储一个数字. 你可以假设除了整数 0 之外,这个整数不会以零开头. 示例 ...
- Linux 只显示目录或者文件方法
ls 参数 -a 表示显示所有文件,包含隐藏文件-d 表示显示目录自身的属性,而不是目录中的内容-F 选项会在显示目录条目时,在目录后加一个/ 只显示目录 方法一: find . -type d -m ...
- python开发的学生管理系统
python开发的学生管理系统(基础版) #定义一个函数,显示可以使用的功能列表给用户 def showInfo(): print("-"*30) print(" 学生管 ...
- React Native开发之expo中camera的基本使用
之前做RN项目没调用过本地摄像头,今天下班早,做了一个简单的小demo:主要实现的功能:点击拍照按钮进入拍照界面,点击flip进行前后摄像头转换,点击开始拍照实现拍照功能(没写保存到本地的功能,大家可 ...