Add base paper and tarjan's SCC algorithm

This commit is contained in:
stefiosif
2022-05-06 12:25:04 +03:00
parent adb36adea7
commit 122d11b189
7 changed files with 186 additions and 67 deletions

3
.gitignore vendored
View File

@@ -24,6 +24,3 @@ x86/
*.vcxproj
*.vcxproj.user
*.vcxproj.filters
*.pdf
*.pptx

74
algorithm/tarjan.h Normal file
View File

@@ -0,0 +1,74 @@
#ifndef TARJAN_H_
#define TARJAN_H_
#include "graph/graph.h"
using namespace graph;
#include <stack>
#include <iostream>
#include <ranges>
#include <iterator>
#include <algorithm>
namespace algorithm {
template<typename T>
class Tarjan {
public:
Tarjan(Graph<T> G) : G(G) {}
void findSCC();
void strongConnect(Vertex<T>& v);
std::uint16_t index = 0;
std::stack<Vertex<T>> S;
private:
Graph<T> G;
};
template<typename T>
void Tarjan<T>::strongConnect(Vertex<T>& v) {
v.index, v.lowlink = index++;
v.onStack = true;
S.push(v);
for (auto& w : v.edges) {
if (w.index == -1) {
// successor w has not yet been visited, recurse on it
strongConnect(w);
v.lowlink = std::min(v.lowlink, w.lowlink);
} else if (w.onStack) {
// successor w is in stack S and hence in the current SCC
// if w is not on stack, then (v, w) is an edge pointing to an SCC
// already found and must be ignored
v.lowlink = std::min(v.lowlink, w.index);
}
}
// if v is a root node, pop the stack and generate an SCC
if (v.lowlink = v.index) {
// start a new SCC
Vertex<T> w;
do {
w = S.top();
S.pop();
// add w to current SCC
} while (w != v);
}
}
template<typename T>
void Tarjan<T>::findSCC() {
for (auto& vertex : G.vertices) {
if (vertex.index == -1) {
strongConnect(vertex);
}
}
}
} // namespace algorithm
#endif

Binary file not shown.

65
graph/graph.h Normal file
View File

@@ -0,0 +1,65 @@
#ifndef GRAPH_H_
#define GRAPH_H_
#include "vertex.h"
#include <map>
#include <set>
#include <vector>
#include <utility>
namespace graph {
template<typename T>
class Graph {
public:
Graph() = default;
// Add vertex v
void insert(Vertex<T>& v);
// Add edge between v and u
void insert(Vertex<T> v, Vertex<T> u);
// Delete vertex v
void erase(Vertex<T>& v);
// Delete edge between v and u
void erase(Vertex<T>& v, Vertex<T>& u);
// Return true if v and u are connected
bool connected(const Vertex<T>& v, const Vertex<T>& u) const;
// Adjacency matrix representation
std::vector<Vertex<T>> vertices;
};
template<typename T>
inline void Graph<T>::insert(Vertex<T>& v) {
vertices.push_back(v);
}
template<typename T>
inline void Graph<T>::insert(Vertex<T> v, Vertex<T> u) {
v.edges.push_back(u);
vertices.push_back(v);
}
template<typename T>
inline void Graph<T>::erase(Vertex<T>& v) {
//
}
template<typename T>
inline void Graph<T>::erase(Vertex<T>& v, Vertex<T>& u) {
//
}
template<typename T>
inline bool Graph<T>::connected(const Vertex<T>& v, const Vertex<T>& u) const {
return false;
}
} // namespace graph
#endif

36
graph/vertex.h Normal file
View File

@@ -0,0 +1,36 @@
#ifndef VERTEX_H_
#define VERTEX_H_
#include <cstdint>
#include <compare>
#include <ostream>
#include <vector>
namespace graph {
template<typename T>
class Vertex {
public:
Vertex() = default;
Vertex(T v) : v(v) {}
T v;
std::uint16_t index = -1;
std::uint16_t lowlink = -1;
bool onStack = false;
std::vector<Vertex<T>> edges;
auto operator<=>(const Vertex&) const = default;
template<typename T>
friend inline std::ostream& operator<<(std::ostream& os, const Vertex<T>& v);
};
template<typename T>
inline std::ostream& operator<<(std::ostream& os, const Vertex<T>& vout) {
return os << vout.v;
}
} // namespace graph
#endif

View File

@@ -1,61 +0,0 @@
#ifndef GRAPH_H_
#define GRAPH_H_
#include <map>
#include <set>
#include <vector>
#include <utility>
namespace graph {
template<typename V>
class Graph {
public:
Graph() = default;
// Add vertex v
void insert(const V& v);
// Add edge between v and u
void insert(const V& v, const V& u);
// Delete vertex v
void erase(const V& v);
// Delete edge between v and u
void erase(const V& v, const V& u);
// Return true if v and u are connected
bool connected(const V& v, const V& u);
private:
std::map<V, std::set<V>> adjacency;
};
template<typename V>
inline void Graph<V>::insert(const V& v) {
adjacency[v];
}
template<typename V>
inline void Graph<V>::insert(const V& v, const V& u) {
adjacency[v].insert(u);
}
template<typename V>
inline void Graph<V>::erase(const V& v) {
adjacency.erase(v);
}
template<typename V>
inline void Graph<V>::erase(const V& v, const V& u) {
adjacency[v].erase(u);
}
template<typename V>
inline bool Graph<V>::connected(const V& v, const V& u) {
return true;
}
} // namespace graph
#endif

View File

@@ -1,11 +1,13 @@
#include <doctest/doctest.h>
#include <cstdint>
#include "graph/graph.h"
using namespace graph;
#include "algorithm/tarjan.h"
#include "include/graph.h"
#include <cstdint>
#include <iostream>
TEST_SUITE("Testing Graph.") {
using namespace graph;
TEST_CASE("Insert vertices/edges.") {
Graph<std::uint16_t> G;
@@ -19,6 +21,12 @@ TEST_SUITE("Testing Graph.") {
G.insert(3, 6);
G.insert(4, 6);
G.insert(5, 6);
Vertex<std::uint16_t> v1(1);
Vertex<std::uint16_t> v2(3);
Vertex<std::uint16_t> v3(5);
algorithm::Tarjan<std::uint16_t> tarjan(G);
tarjan.findSCC();
// CHECK_EQ(G.connected(1, 5), true);