Make class Graph abstract and make derived classes Digraph and SCC
This commit is contained in:
@@ -1,23 +1,23 @@
|
||||
#ifndef TARJAN_H_
|
||||
#define TARJAN_H_
|
||||
|
||||
#include "graph/graph.h"
|
||||
using namespace graph;
|
||||
#include "graph/digraph.h"
|
||||
#include "graph/scc.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <ranges>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
|
||||
using namespace graph;
|
||||
|
||||
namespace algo {
|
||||
|
||||
template<typename T>
|
||||
class Tarjan {
|
||||
public:
|
||||
Tarjan(Graph<T> G) : G(G) {}
|
||||
Tarjan(Digraph<T> G) : G(G) {}
|
||||
|
||||
//
|
||||
std::vector<std::vector<T>> run();
|
||||
std::vector<SCC<T>> run();
|
||||
|
||||
//
|
||||
void strongConnect(const T& v);
|
||||
@@ -29,48 +29,48 @@ private:
|
||||
bool onStack = false;
|
||||
};
|
||||
|
||||
Graph<T> G;
|
||||
Digraph<T> G;
|
||||
std::stack<T> S;
|
||||
std::int16_t index = 0;
|
||||
std::map<T, Payload> vp;
|
||||
std::vector<std::vector<T>> SCCs;
|
||||
std::map<T, Payload> p;
|
||||
std::vector<SCC<T>> SCCs;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void Tarjan<T>::strongConnect(const T& v) {
|
||||
vp[v].index = vp[v].lowlink = index++;
|
||||
vp[v].onStack = true;
|
||||
p[v].index = p[v].lowlink = index++;
|
||||
p[v].onStack = true;
|
||||
S.push(v);
|
||||
|
||||
for (const auto& w : G.adjMatrix[v]) {
|
||||
if (vp[w].index == -1) {
|
||||
if (p[w].index == -1) {
|
||||
strongConnect(w);
|
||||
vp[v].lowlink = std::min(vp[v].lowlink, vp[w].lowlink);
|
||||
} else if (vp[w].onStack) {
|
||||
vp[v].lowlink = std::min(vp[v].lowlink, vp[w].index);
|
||||
p[v].lowlink = std::min(p[v].lowlink, p[w].lowlink);
|
||||
} else if (p[w].onStack) {
|
||||
p[v].lowlink = std::min(p[v].lowlink, p[w].index);
|
||||
}
|
||||
}
|
||||
|
||||
// If v is a root node, pop the stack and generate an SCC
|
||||
if (vp[v].lowlink == vp[v].index) {
|
||||
std::vector<T> SCC;
|
||||
if (p[v].lowlink == p[v].index) {
|
||||
//std::vector<T> scc;
|
||||
std::map<T, std::set<T>> scc;
|
||||
bool finished = false;
|
||||
do {
|
||||
const auto w = S.top();
|
||||
S.pop();
|
||||
vp[w].onStack = false;
|
||||
SCC.push_back(w);
|
||||
finished = vp[w].index == vp[v].index;
|
||||
p[w].onStack = false;
|
||||
scc[w] = G.adjMatrix[w];
|
||||
finished = p[w].index == p[v].index;
|
||||
} while (!finished);
|
||||
SCCs.push_back(SCC);
|
||||
SCCs.push_back(scc);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::vector<std::vector<T>> Tarjan<T>::run() {
|
||||
|
||||
std::vector<SCC<T>> Tarjan<T>::run() {
|
||||
for (const auto& v : G.vertices) {
|
||||
if (vp[v].index == -1) {
|
||||
if (p[v].index == -1) {
|
||||
strongConnect(v);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user