Skip to content

Commit

Permalink
Merge pull request #94 from CSRT-NTUA/spiros-dev
Browse files Browse the repository at this point in the history
Added scc function on weighted graph
  • Loading branch information
spirosmaggioros authored Nov 28, 2024
2 parents 40e6b88 + 6074251 commit aa4d393
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 1 deletion.
69 changes: 68 additions & 1 deletion src/classes/graph/graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ template <typename T> int64_t graph<T>::scc() {

std::unordered_map<T, std::vector<T> > new_adj;
for(const T& x: _elements) {
for(auto & neigh: adj[x]) {
for(const auto& neigh: adj[x]) {
new_adj[neigh].push_back(x);
}
}
Expand Down Expand Up @@ -866,6 +866,20 @@ template <typename T> class weighted_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.first) == visited.end()) {
dfs_scc(x.first, visited, s);
}
}

s.push(start);
}
};

template <typename T> size_t weighted_graph<T>::size() {
Expand Down Expand Up @@ -1144,6 +1158,59 @@ std::vector<std::vector<T>> weighted_graph<T>::bridge(T start) {
return bridges;
}

template <typename T>
int64_t weighted_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(const auto& neigh: adj[x]) {
new_adj[neigh.first].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> bool weighted_graph<T>::connected() {
std::unordered_map<T, bool> visited;
bool check = 0;
Expand Down
51 changes: 51 additions & 0 deletions tests/graph/weighted_graph.cc
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,57 @@ TEST_CASE("Testing shortest path algorithm [2]") {
REQUIRE(g.shortest_path(1, 7) == 56);
}

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

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

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

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

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

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

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

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

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

#define GRAPH_VISUALIZATION_H

#ifdef GRAPH_VISUALIZATION_H
Expand Down

0 comments on commit aa4d393

Please sign in to comment.