kosaraju 和 tarjan算法详解(强连通分量)

本文介绍了有向图的强连通性,并详细阐述了kosaraju算法和tarjan算法在找寻强连通分量上的应用。kosaraju算法通过两次深度优先遍历实现,而tarjan算法则利用low和dfn数组及栈来寻找强连通分量。此外,文章还探讨了有向无环图中的相关性质和缩点建图的方法。
摘要由CSDN通过智能技术生成

定 义
在有向图G中,如果任意两个不同的顶点相互可达,则称该有向图是强连通的。
有向图G的极大强连通子图称为G的强连通分支。
 转置图的定义:将有向图G中的每一条边反向形成的图称为G的转置GT 。(注意到原图和GT 的强连通分支是一样的)

Korasaju算法

 1.深度优先遍历G,算出每个结点u的结束时间f[u],起点如何选择无所谓。

    每个结点的结束时间和开始时间是dfs序,开始时间是此点第一次被遍历到时,结束时间为此点已经没法拓展,从栈中弹出,即已经遍历结束,不懂dfs序,可以看这个dfs序
 2.深度优先遍历G的转置图GT ,选择遍历的起点时,按照结点的结束时间从大到小进行。遍历的过程中,
     一边遍历,一边给结点做分类标记,每找到一个新的起点,分类标记值就加1。

    如果此节点已经在反图中遍历过,就不再从它遍历,挑选下一个结束时间晚的
 3. 第2步中产生的标记值相同的结点构成深度优先森林中的一棵树,也即一个强连通分量

至于证明。。。emmm,我没看懂,就自己想了一下

 如果正图中 b->a,那么反图中为 a->b,而b的结束时间一定比a要晚,所以先遍历b,如果b->a,则说明在原图中a->b


 

#include<bits/stdc++.h>
using namespace std;
int f[1000][1000];//存储正图 
int rf[1000][1000];//存储反图 
int vis[1000];
stack<int> s;//用来存储节点离开时间 
stack<int> s1[1000];
int n;
//对原图dfs,找出每个节点的离开时间,用栈存储,直接pop,就不用再逆序 
void dfs(int a){
	vis[a]=1;
	for(int i=1;i<=n;i++){
		if(f[a][i]&&!vis[i]){
			dfs(i);
		}
	}
	s.push(a);
}
void rdfs(int a,int k){
	vis[a]=1;
	for(int i=1;i<=n;i++){
		if(rf[a][i]&&!vis[i]){
			rdfs(i,k);
		}
	}
	s1[k].push(a);//对每个连通分量分支,记录下来 
}
int main(){
	int m;
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		f[x][y]=1;
		rf[y][x]=1;
	}
	//对原图dfs 
	for(int i=1;i<=n;i++){
		if(!vis[i])
		dfs(1);
	}
	memset(vis,0,sizeof(vis));
	int k=0;
	//对反图dfs 
	while(!s.empty()){
		if(!vis[s.top()])//节点按照节点离开时间从大到小遍历 
		rdfs(s.top(),++k);//计算连通分量个数 
		s.pop();
	} 
	cout<<k<<endl;
	//输出 
	for(int i=1;i<=k;i++){
		while(!s1[i].empty()){
			cout<<s1[i].top();
			s1[i].pop();
		}
		cout<<endl;
	}
	return 0;
}

用邻接表写的代码(老师写的)

#include <cstdio>
#include <cstring>
const int V = 1e4 + 7, E = 5e4 + 7;
int hd[V], to[E], fr[E], nt[E], pr[E], tl[E];
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值