Tarjan算法模板-求图的强连通分量算法模板C/C++代码实现内有详细注释

#include <bits/stdc++.h>
using namespace std;

//设置最大节点数 
const int maxv = 10005;

//邻接表中的节点结构体,next代表后继节点编号 
struct node{
	int next;
	node(int _n):next(_n){}
};

//DFN数组记录每个节点入栈的时间戳,DFN另一个作用可以检测该节点是否已经访问过;
//LOW节点记录每个节点的最小根节点 
int DFN[maxv],LOW[maxv];
//时间戳,相当于计时器,每搜索到一个节点index+1 
int index = 1;
//栈容器,每搜索到一个节点就将他入栈,等找到一个强连通分量之后就将该强连通分量的所有节点出栈 
int vstack[maxv];
//栈顶指针 
int top = -1;
//记录节点是否在栈中 
int flag[maxv];
//图的邻接表 
vector<node> maze[maxv];
int n,m,ans;


//tarjan核心算法: 
void tarjan(int u){
	//每来访问一个几点,记录该节点的时间戳,并初始化它的最小根节点LOW 
	DFN[u]=LOW[u] = index++;
	//节点入栈 
	vstack[++top]=u;
	//置入栈标识为1 
	flag[u]=1;
	
	//遍历当前节点的所有后继节点 
	for(int i=0;i<maze[u].size();i++){
		//后继节点v 
		int v = maze[u][i].next;
		//如果v没有被访问过,就递归进入tarjan(v),回来之后取最小的根节点给LOW[u]
		//如果v被访问并且v在栈中,LOW[u]与DFN[v]的较小值给LOW[u] 
		if(!DFN[v]){
			tarjan(v);
			LOW[u] = min(LOW[u],LOW[v]);
		}else if(flag[v]){
			LOW[u] = min(LOW[u],DFN[v]);
		}
	}
	//如果DFN[u]=LOW[u]说明已经找到了强连通分量,可以进行输出等相关操作 
	if(DFN[u]==LOW[u]){
		//int num=0;
		do{
			//此处可以进行一系列相关操作,根据需要进行修改! 
			
			j = vstack[top--];//取出强连通分量里面的节点,出栈 
			//num++;
			flag[j]=0;//并置此节点不在栈中 
		}while(j!=u);
		//ans = ans+num*(num-1)/2;
	}
}

int main(){
	//初始化操作 
	fill(DFN,DFN+maxv,0);
	fill(LOW,LOW+maxv,0);
	fill(flag,flag+maxv,0);
	scanf("%d %d",&n,&m);
	for(int i=0;i<m;i++){
		int x,y;
		scanf("%d %d",&x,&y);
		maze[x].push_back(node(y));
	}
	for(int i=0;i<n;i++){
		if(!DFN[i])tarjan(i);
	}
	//printf("%d\n",ans);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值