Tarjan算法的C++实现

本文详细介绍了强连通分量算法的核心内容,包括如何使用Tarjan算法进行求解,以及如何通过DFS遍历图并标记节点状态,最终输出所有强连通分量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

bool GraphList::FindSCC(int index, int *dfn, int *low, int &tStamp, stack<int> &aStack){
	dfn[index] = low[index] = ++tStamp;
	this->mark[index] = DISCOVERED;  //DISCOVERED
	aStack.push(index);
	//遍历相邻结点
	for(Edge e = FirstEdge(graList[index].vertexId); e.to >= 0; e = NextEdge(e)) {
		int j = this->id2index[e.to];
		if(mark[j] == UNVISITED) { //UNVISITED没有访问过
			FindSCC(j, dfn, low, tStamp, aStack);
			if(low[j] < low[index]) { //树边传递low值
				low[index] = low[j];
			} 
		}
		else if(mark[j] == DISCOVERED && dfn[j] < low[index]) {
			low[index] = dfn[j];
		}
	}
	//回溯
	if(dfn[index] == low[index]) {
		set<int> aSCC;
		int top;
		do{
			top = aStack.top();
			aStack.pop();
			aSCC.insert(top);
			mark[top] = FINISHED;
		}while(top != index);
		this->vecSCC.push_back(aSCC);
	}
	return true;
}

bool GraphList::FindSCC(){
	RmSelfcirles();
	vecSCC.clear();
	int *dfn = new int[this->numVertex + 1];
	int *low = new int[this->numVertex + 1];
	if(!dfn || !low) {
		cerr << "GraphList::RmCirlesTarjan: Memery alocate fail!" << endl;
		return false;
	}

	int tStamp = 0;
	memset(dfn, 0, numVertex * sizeof(int));
	memset(low, 0, numVertex * sizeof(int));
	for(int i = 0; i < this->numVertex; i ++){
		this->mark[i] = UNVISITED;
	}
	for(int i = 0; i < this->numVertex; i ++) {
		id2index[this->graList[i].vertexId] = i;
	}
	stack<int> aStack;
	for(int i = 0; i < this->numVertex; i ++){
		if(this->mark[i] == UNVISITED) {
			FindSCC(i, dfn, low, tStamp, aStack);
		}
	}

	for(unsigned i = 0; i < this->vecSCC.size(); i ++){
		cout << "强连通分量" << i + 1 << ":" << endl;
		set<int> aSCC = vecSCC[i];
		for(set<int>::iterator iter = aSCC.begin(); iter != aSCC.end(); iter ++) {
			cout << *iter << "\t";
		}
		cout << endl;
	}

	delete []dfn;
	delete []low;
	return true;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值