Skip to content

Commit

Permalink
Merge pull request #93 from CSRT-NTUA/spiros-dev
Browse files Browse the repository at this point in the history
Added scc function for graph class
  • Loading branch information
spirosmaggioros authored Nov 25, 2024
2 parents daf7bc2 + e9614a7 commit 40e6b88
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 1 deletion.
68 changes: 67 additions & 1 deletion src/classes/graph/graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ template <typename T> class graph {

/**
*@brief scc(strongly connected components) function.
*@returns int64_t the number of scc's in the graph.
*@returns int64_t the number of scc's in the graph using kosaraju's algorithm.
*/
int64_t scc();

Expand Down Expand Up @@ -254,6 +254,20 @@ template <typename T> class graph {
}
}
}

/**
* @brief helper dfs function for kosaraju's scc
*/
void dfs_scc(T start, std::unordered_map<T, bool> &visited, std::stack<T> &s) {
visited[start] = true;
for(auto & x : adj[start]) {
if(visited.find(x) == visited.end()) {
dfs_scc(x, visited, s);
}
}

s.push(start);
}
};

template <typename T> size_t graph<T>::size() { return _elements.size(); }
Expand Down Expand Up @@ -477,6 +491,58 @@ template <typename T> bool graph<T>::connected() {
return true;
}

template <typename T> int64_t graph<T>::scc() {
if (this -> size() == 0) {
return 0;
}

std::unordered_map<T, bool> visited;
std::stack<T> s;

for(const T& x: _elements) {
if(visited.find(x) == visited.end()) {
dfs_scc(x, visited, s);
}
}

std::unordered_map<T, std::vector<T> > new_adj;
for(const T& x: _elements) {
for(auto & neigh: adj[x]) {
new_adj[neigh].push_back(x);
}
}

int64_t scc = 0;
visited.clear();

auto dfs_new = [&](T start) -> void {
std::stack<T> _s;
_s.push(start);
visited[start] = true;
while(!_s.empty()) {
T current = _s.top();
_s.pop();
for(auto & x: new_adj[current]) {
if (visited.find(x) == visited.end()) {
_s.push(x);
visited[x] = true;
}
}
}
};

while(!s.empty()) {
T current = s.top();
s.pop();
if (visited.find(current) == visited.end()) {
dfs_new(current);
scc++;
}
}

return scc;
}

template <typename T> int graph<T>::eulerian() {
if (this->connected() == false) {
return false;
Expand Down
52 changes: 52 additions & 0 deletions tests/graph/graph.cc
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,58 @@ TEST_CASE("Testing clear function for graph class") {
REQUIRE(bfs_path.size() == 0);
}

TEST_CASE("Testing scc function for graph class") {
graph<int> g("directed");
g.add_edge(0, 1);
g.add_edge(1, 2);
g.add_edge(2, 0);
g.add_edge(1, 3);
g.add_edge(3, 4);
g.add_edge(4, 3);

REQUIRE(g.scc() == 2);

graph<int> g2("undirected");
REQUIRE(g2.scc() == 0);

g2.add_edge(0, 1);
g2.add_edge(1, 2);
g2.add_edge(2, 0);
g2.add_edge(3, 4);
g2.add_edge(4, 5);
g2.add_edge(5, 3);
g2.add_edge(3, 6);
g2.add_edge(1, 3);

REQUIRE(g2.scc() == 1);

graph<char> t("directed");
t.add_edge('a', 'b');
t.add_edge('b', 'c');
t.add_edge('c', 'a');
t.add_edge('b', 'd');
t.add_edge('d', 'e');
t.add_edge('e', 'd');

REQUIRE(t.scc() == 2);


graph<int> g3("directed");
g3.add_edge(0, 1);
g3.add_edge(1, 2);
g3.add_edge(2, 0);
g3.add_edge(1, 3);
g3.add_edge(3, 4);
g3.add_edge(4, 5);
g3.add_edge(5, 3);
g3.add_edge(3, 6);
g3.add_edge(6, 7);
g3.add_edge(6, 8);
g3.add_edge(8, 6);

REQUIRE(g3.scc() == 4);
}

#define GRAPH_VISUALIZATION_H
#ifdef GRAPH_VISUALIZATION_H
TEST_CASE("Testing visualize for graph class") {
Expand Down
7 changes: 7 additions & 0 deletions tests/graph/unnamed.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
digraph G{
3->4
2->3
1->2
0->1

}

0 comments on commit 40e6b88

Please sign in to comment.