Add base paper and tarjan's SCC algorithm
This commit is contained in:
74
algorithm/tarjan.h
Normal file
74
algorithm/tarjan.h
Normal 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
|
||||
Reference in New Issue
Block a user