#include <iostream>
using namespace std;
struct Vertex {
int index{ -1 };
Vertex* next{ nullptr };
};
enum class COLOR {
WHITE, GRAY, BLACK
};
struct Node {
int d{};
int f{};
COLOR color{ COLOR::WHITE };
};
void recurse_delete(Vertex* v) {
if (v->next) {
recurse_delete(v->next);
}
else {
delete v;
}
}
void delete_list(Vertex* V, size_t n) {
Vertex* head{};
Vertex* p{};
for (int i = 0; i < n; ++i) {
head = &V[i];
if ((p = head->next)) {
recurse_delete(p);
}
}
delete[]V;
}
void insert(Vertex* V, int from, int to) {
Vertex* head = &V[from];
Vertex* p = head->next;
head->next = new Vertex{};
head->next->index = to;
head->next->next = p;
}
void DFS_VISIT(Vertex* V, Node* N, int u, int& time) {
time++;
N[u].color = COLOR::GRAY;
N[u].d = time;
Vertex* head = &V[u];
Vertex* p = head->next;
while (p) {
if (N[p->index].color == COLOR::WHITE) {
DFS_VISIT(V, N, p->index, time);
}
p = p->next;
}
N[u].color = COLOR::BLACK;
time++;
N[u].f = time;
}
void DFS(Vertex* V, Node* N, size_t n, int start, int& time) {
if (N[start].color == COLOR::WHITE) {
DFS_VISIT(V, N, start, time);
}
for (int i = 0; i < n; ++i) {
if (N[i].color == COLOR::WHITE) {
DFS_VISIT(V, N, i, time);
}
}
}
void sort_f(int* f, Node* N, size_t n) {
int* flag = new int[n]{};
for (int i = 0; i < n; ++i) {
int f_max{};
int max_index{};
for (int j = 0; j < n; ++j) {
if (N[j].f > f_max && !flag[j]) {
f_max = N[j].f;
max_index = j;
}
}
f[i] = max_index;
flag[max_index] = 1;
}
}
void built_VT(Vertex* VT, Vertex* V, int* Matrix_T, int* f, size_t n) {
Vertex* head{};
Vertex* p{};
for (int i = 0; i < n; ++i) {
head = &VT[i];
p = head->next;
for (int j = n - 1; j >= 0; --j) {
if (Matrix_T[i * n + f[j]] == 1) {
head->next = new Vertex{};
head->next->index = f[j];
head->next->next = p;
p = head->next;
}
}
}
}
void initial_nodes_color(Node* N, size_t n) {
for (int i = 0; i < n; ++i) {
N[i].color = COLOR::WHITE;
}
}
void DFS_VISIT_T(Vertex* VT, Node* N, size_t n, int u) {
cout << u << " ";
N[u].color = COLOR::GRAY;
Vertex* head = &VT[u];
Vertex* p = head->next;
while (p) {
if (N[p->index].color == COLOR::WHITE) {
DFS_VISIT_T(VT, N, n, p->index);
}
p = p->next;
}
N[u].color = COLOR::BLACK;
}
void DFS_T(Vertex* VT, Node* N, int* f, size_t n) {
DFS_VISIT_T(VT, N, n, f[0]);
cout << endl;
for (int i = 0; i < n; ++i) {
if (N[f[i]].color == COLOR::WHITE) {
DFS_VISIT_T(VT, N, n, f[i]);
cout << endl;
}
}
}
void STRONG_CONNECTED_COMPONENTS(Vertex* V, int* Matrix_T, size_t n) {
int start{};
Node* N = new Node[n] {};
cout << "please choose which vertex do you want to start DFS :" << endl;
cin >> start;
int time{};
DFS(V, N, n, start, time);
int* f_array = new int[n]{};
sort_f(f_array, N, n);
Vertex* VT = new Vertex[n] {};
built_VT(VT, V, Matrix_T, f_array, n);
initial_nodes_color(N, n);
cout << "the strong connected components as follow :" << endl;
DFS_T(VT, N, f_array, n);
delete[]f_array;
delete[]N;
delete_list(VT, n);
}
int main(int argc, char* argv[]) {
size_t vertex_size{};
cout << "please input the numbers of vertexs :" << endl;
cin >> vertex_size;
Vertex* V = new Vertex[vertex_size] {};
int* Matrix_T = new int[vertex_size * vertex_size] {};
cout << "please enter the edges : (eg : 0 1 presents there is a edge between v0 and v1, and end with -1 -1)" << endl;
int from{};
int to{};
while (true) {
cout << "edge :" << endl;
cin >> from >> to;
if (from != -1 && to != -1) {
Matrix_T[to * vertex_size + from] = 1;
insert(V, from, to);
}
else {
break;
}
}
STRONG_CONNECTED_COMPONENTS(V, Matrix_T, vertex_size);
delete_list(V, vertex_size);
delete[]Matrix_T;
return 0;
}