导读我就不写了,详情参考《算法导论》(第三版)p357。以下代码使用Trajin算法,版权所有
/*
This programme is designed to realize scc
editor Xiangyu Lv
email:lvxiangyu11@gmail.com
2018年3月29日20:30:47
ALL RIGHTS RESERVED!
*/
#include<iostream>
#include<vector>
#include<stack>
#include<ctime>
#define min(a,b) (a)<(b)?a:b;
using namespace std;
typedef int Vertex;
typedef int Weight;
class GraphList {
public:
explicit GraphList() {
List.resize(0);
NameLoc.resize(0);
}
void insert(Vertex v0, Vertex v1, Weight weight) {
int v0Loc = find(v0);
if (v0Loc == -1)
v0Loc = _Insert_In_List(v0);
int v1Loc = find(v1);
if (v1Loc == -1)
v1Loc = _Insert_In_List(v1);
EdgeNode * newEdgePtr = new EdgeNode;
newEdgePtr->BratherNode = List[v0Loc].jointEdge;
newEdgePtr->weight = weight;
newEdgePtr->Loc = v1Loc;
newEdgePtr->vertex = v1;
List[v0Loc].jointEdge = newEdgePtr;
}
void Tarjin() {
//initialization
dfn.resize(List.size(), -1);
low.resize(List.size(), -1);
colour.resize(List.size(), -1);
time = 0;
count = 0;
for (size_t i = 0; i < List.size(); i++) {
if (colour[i] == -1)
TarjinDFS(i);
}
}
private:
struct EdgeNode//存边
{
Vertex vertex;//邻接到的点的名称
int Loc;//在List内的位置
Weight weight;//权值
EdgeNode * BratherNode;
};
struct ListStack//数组节点
{
Vertex vertex;
Weight weight;
EdgeNode * jointEdge;
};
//struct VisitTime {
// size_t begin;//记录访问到时候的时间
// size_t end;//记录回溯时的时间
//};
vector<ListStack> List;
vector<Vertex> NameLoc;//名称存储数组
vector<int> dfn;//dfn数组记录搜索到该点时的时间
vector<int> low;//记录点u所在强连通子图对应的搜索子树的根节点的dfs值
vector<int> colour;
stack<int> st;//存储每遍历到一个未被标记的点的下标,每当搜索到一个点并经过以上步骤后,其low值等于dfn值,则将它以及在它之上的元素弹出栈。这些出栈元素组成一个强连通分量。
int count;//记录set数量
size_t time;//记录DFS时的访问时间
int find(Vertex v0) {//成功返回下标,失败返回-1
for (size_t i = 0; i < NameLoc.size(); i++)
if (NameLoc[i] == v0)
return i;
return -1;
}
int _Insert_In_List(Vertex v0) {
ListStack newStack;
newStack.vertex = v0;
newStack.weight = 0;
newStack.jointEdge = nullptr;
List.push_back(newStack);
NameLoc.push_back(v0);
return List.size() - 1;
}
void TarjinDFS(int vLoc) {//传递点的下标
colour[vLoc] = 0;
cout << "访问" << List[vLoc].vertex << endl;
dfn[vLoc] =low[vLoc] = ++time;
st.push(vLoc);
EdgeNode *NextNode = List[vLoc].jointEdge;
while (NextNode!=nullptr) {
if (colour[NextNode->Loc] == -1) {
TarjinDFS(NextNode->Loc);
low[vLoc] = min(low[vLoc], low[NextNode->Loc]);
}
else {
low[vLoc] = min(low[vLoc], dfn[NextNode->Loc]);
}
NextNode = NextNode->BratherNode;
}
if (dfn[vLoc] == low[vLoc]) {
int vtx;
cout << "Set " << count++<<":";
do {
vtx = st.top();
st.pop();
cout << List[vtx].vertex<<" ";
} while (vtx != vLoc);
cout << endl;
}
cout<<"退出"<<List[vLoc].vertex<<endl;
colour[vLoc] = 1;
}
};
int main()
{
GraphList MyGraphList;
int i = 0;
cin >> i;
for (int j = 0; j < i; j++) {
Vertex v0, v1, w;
cin >> v0 >> v1 >> w;
MyGraphList.insert(v0, v1, w);
}
MyGraphList.Tarjin();
system("pause");
return 0;
}
样例输入:
,
![](https://i-blog.csdnimg.cn/blog_migrate/f35ff63b0cb9532bb579477f6bc49509.png)
Input:
8
1 2 1
3 4 1
4 6 1
4 1 1
2 4 1
1 3 1
3 5 1
5 6 1
Output:
访问1
访问3
访问5
访问6
Set 0:6
退出6
Set 1:5
退出5
访问4
退出4
退出3
访问2
退出2
Set 2:2 4 3 1
退出1