Use clang-format
This commit is contained in:
@@ -8,8 +8,7 @@
|
||||
|
||||
namespace algo {
|
||||
|
||||
template<typename T>
|
||||
class Frigioni : public DecrementalReachability<T> {
|
||||
template <typename T> class Frigioni : public DecrementalReachability<T> {
|
||||
public:
|
||||
Frigioni() = default;
|
||||
|
||||
@@ -20,10 +19,11 @@ public:
|
||||
|
||||
// Execute reachability query q(u, v) from vertex u to vertex v
|
||||
// in O(1) using the transitive closure matrix
|
||||
bool query(const T& u, const T& v) override;
|
||||
bool query(const T &u, const T &v) override;
|
||||
|
||||
// Delete set of edges and explicitely maintain the transitive closure
|
||||
void remove(const std::vector<std::pair<T, T>>& edges) override;
|
||||
void remove(const std::vector<std::pair<T, T>> &edges) override;
|
||||
|
||||
private:
|
||||
// Transitive closure matrix, used to answer reachability queries in O(1)
|
||||
std::unordered_map<T, std::unordered_map<T, bool>> TC;
|
||||
@@ -46,161 +46,162 @@ private:
|
||||
RodittyZwick<T> rodittyZwick;
|
||||
|
||||
// Delete internal edge e(u, v)
|
||||
void removeInternal(const T& u, const T& v);
|
||||
void removeInternal(const T &u, const T &v);
|
||||
|
||||
// Delete external edge e(u, v)
|
||||
void removeExternal(const T& u, const T& v);
|
||||
void removeExternal(const T &u, const T &v);
|
||||
|
||||
// Repair reachability trees
|
||||
void repairTrees();
|
||||
|
||||
//
|
||||
void splitEdges(std::unordered_map<T, SCC<T>>& L, std::unordered_map<T, SCC<T>> C, const T& w);
|
||||
//
|
||||
void splitEdges(std::unordered_map<T, SCC<T>> &L,
|
||||
std::unordered_map<T, SCC<T>> C, const T &w);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void Frigioni<T>::init() {
|
||||
template <typename T> void Frigioni<T>::init() {
|
||||
rodittyZwick = RodittyZwick<T>(this->G);
|
||||
rodittyZwick.init();
|
||||
auto C = rodittyZwick.getComponentMap();
|
||||
|
||||
for (const auto& w : std::views::keys(C)) {
|
||||
for (const auto &w : std::views::keys(C)) {
|
||||
RT[C[w]] = BreadthFirstTree<T>(this->G, w);
|
||||
for (const auto& u : this->G.vertices()) {
|
||||
for (const auto& v : this->G.adjList[u]) {
|
||||
for (const auto &u : this->G.vertices()) {
|
||||
for (const auto &v : this->G.adjList[u]) {
|
||||
if (!C[w].contains(u) && C[w].contains(v))
|
||||
E[C[w]].inc.insert({ u, v });
|
||||
E[C[w]].inc.insert({u, v});
|
||||
else if (C[w].contains(u) && !C[w].contains(v))
|
||||
E[C[w]].out.insert({ u, v });
|
||||
E[C[w]].out.insert({u, v});
|
||||
else
|
||||
E[C[w]].in.insert({ u, v });
|
||||
E[C[w]].in.insert({u, v});
|
||||
TC[u][v] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const auto& w : std::views::keys(C)) {
|
||||
for (const auto& u : C[w].vertices()) {
|
||||
for (const auto& v : RT[C[w]].vertices()) {
|
||||
for (const auto &w : std::views::keys(C)) {
|
||||
for (const auto &u : C[w].vertices()) {
|
||||
for (const auto &v : RT[C[w]].vertices()) {
|
||||
TC[u][v] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Frigioni<T>::query(const T& u, const T& v) {
|
||||
template <typename T> bool Frigioni<T>::query(const T &u, const T &v) {
|
||||
return TC[u][v];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Frigioni<T>::remove(const std::vector<std::pair<T, T>>& edges) {
|
||||
template <typename T>
|
||||
void Frigioni<T>::remove(const std::vector<std::pair<T, T>> &edges) {
|
||||
std::vector<std::pair<T, T>> Eint;
|
||||
std::vector<std::pair<T, T>> Eext;
|
||||
|
||||
for (const auto& [u, v] : edges) {
|
||||
if (!this->G.adjList[u].contains(v)) continue;
|
||||
for (const auto &[u, v] : edges) {
|
||||
if (!this->G.adjList[u].contains(v))
|
||||
continue;
|
||||
|
||||
if (rodittyZwick.query(u, v))
|
||||
Eint.push_back({ u, v });
|
||||
Eint.push_back({u, v});
|
||||
else
|
||||
Eext.push_back({ u, v });
|
||||
Eext.push_back({u, v});
|
||||
}
|
||||
for (const auto& [u, v] : Eint) removeInternal(u, v);
|
||||
for (const auto& [u, v] : Eext) removeExternal(u, v);
|
||||
for (const auto &[u, v] : Eint)
|
||||
removeInternal(u, v);
|
||||
for (const auto &[u, v] : Eext)
|
||||
removeExternal(u, v);
|
||||
|
||||
repairTrees();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Frigioni<T>::removeInternal(const T& u, const T& v) {
|
||||
template <typename T> void Frigioni<T>::removeInternal(const T &u, const T &v) {
|
||||
this->G.remove(u, v);
|
||||
auto L = rodittyZwick.getComponentMap();
|
||||
rodittyZwick.remove(u, v);
|
||||
auto C = rodittyZwick.getComponentMap();
|
||||
|
||||
if (rodittyZwick.query(u, v)) {
|
||||
E[C[u]].in.erase({ u, v });
|
||||
E[C[u]].in.erase({u, v});
|
||||
return;
|
||||
}
|
||||
|
||||
if (L[u] == C[u]) {
|
||||
E[L[u]].out.erase({ u, v });
|
||||
E[L[u]].out.erase({u, v});
|
||||
E.erase(L[v]);
|
||||
splitEdges(L, C, v);
|
||||
}
|
||||
else {
|
||||
E[L[v]].inc.erase({ u, v });
|
||||
} else {
|
||||
E[L[v]].inc.erase({u, v});
|
||||
E.erase(L[u]);
|
||||
splitEdges(L, C, u);
|
||||
}
|
||||
|
||||
for (const auto& w : std::views::keys(C)) {
|
||||
if (!RT[C[w]].contains(v)) continue;
|
||||
for (const auto &w : std::views::keys(C)) {
|
||||
if (!RT[C[w]].contains(v))
|
||||
continue;
|
||||
|
||||
RT[C[w]].removeEdgeTo(v);
|
||||
if (E[C[v]].inc.size() > 0) {
|
||||
H[C[w]].push(v); /*h mipos C[v].id?*/
|
||||
continue;
|
||||
}
|
||||
for (const auto& x : C[w].vertices()) {
|
||||
for (const auto& y : C[v].vertices()) {
|
||||
for (const auto &x : C[w].vertices()) {
|
||||
for (const auto &y : C[v].vertices()) {
|
||||
TC[x][y] = false;
|
||||
}
|
||||
}
|
||||
for (const auto& [a, b] : E[C[v]].out)
|
||||
for (const auto &[a, b] : E[C[v]].out)
|
||||
H[C[w]].push(b);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Frigioni<T>::removeExternal(const T& u, const T& v) {
|
||||
template <typename T> void Frigioni<T>::removeExternal(const T &u, const T &v) {
|
||||
this->G.remove(u, v);
|
||||
auto C = rodittyZwick.getComponentMap();
|
||||
E[C[v]].inc.erase({ u, v });
|
||||
E[C[u]].out.erase({ u, v });
|
||||
E[C[v]].inc.erase({u, v});
|
||||
E[C[u]].out.erase({u, v});
|
||||
|
||||
for (const auto& w : std::views::keys(C)) {
|
||||
if (!RT[C[w]].contains(v)) continue;
|
||||
for (const auto &w : std::views::keys(C)) {
|
||||
if (!RT[C[w]].contains(v))
|
||||
continue;
|
||||
|
||||
RT[C[w]].removeEdgeTo(v);
|
||||
if (E[C[v]].inc.size() > 0) {
|
||||
H[C[w]].push(v);
|
||||
continue;
|
||||
}
|
||||
for (const auto& x : C[w].vertices()) {
|
||||
for (const auto& y : C[v].vertices()) {
|
||||
for (const auto &x : C[w].vertices()) {
|
||||
for (const auto &y : C[v].vertices()) {
|
||||
TC[x][y] = false;
|
||||
}
|
||||
}
|
||||
for (const auto& [a, b] : E[C[v]].out)
|
||||
for (const auto &[a, b] : E[C[v]].out)
|
||||
H[C[w]].push(b);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Frigioni<T>::repairTrees() {
|
||||
template <typename T> void Frigioni<T>::repairTrees() {
|
||||
auto C = rodittyZwick.getComponentMap();
|
||||
for (const auto& w : std::views::keys(C)) {
|
||||
for (const auto &w : std::views::keys(C)) {
|
||||
while (H[C[w]].size() > 0) {
|
||||
const auto& h = H[C[w]].top();
|
||||
const auto &h = H[C[w]].top();
|
||||
H[C[w]].pop();
|
||||
bool foundHook = false;
|
||||
|
||||
for (const auto& [a, b] : E[C[h]].inc) {
|
||||
for (const auto &[a, b] : E[C[h]].inc) {
|
||||
if (RT[C[w]].adjList[w].contains(a)) {
|
||||
RT[C[w]].insert(a, h);
|
||||
foundHook = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (foundHook) continue;
|
||||
if (foundHook)
|
||||
continue;
|
||||
|
||||
for (const auto& x : C[w].vertices()) {
|
||||
for (const auto& y : C[h].vertices()) {
|
||||
for (const auto &x : C[w].vertices()) {
|
||||
for (const auto &y : C[h].vertices()) {
|
||||
TC[x][y] = false;
|
||||
}
|
||||
}
|
||||
for (const auto& [a, b] : E[C[h]].out) {
|
||||
for (const auto &[a, b] : E[C[h]].out) {
|
||||
if (RT[C[w]].adjList[h].contains(a)) {
|
||||
H[C[w]].push(b);
|
||||
}
|
||||
@@ -209,21 +210,21 @@ void Frigioni<T>::repairTrees() {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Frigioni<T>::splitEdges(std::unordered_map<T, SCC<T>>& L, std::unordered_map<T, SCC<T>> C, const T& w) {
|
||||
for (const auto& [a, b] : E[L[w]].inc)
|
||||
E[C[b]].inc.insert({ a, b });
|
||||
template <typename T>
|
||||
void Frigioni<T>::splitEdges(std::unordered_map<T, SCC<T>> &L,
|
||||
std::unordered_map<T, SCC<T>> C, const T &w) {
|
||||
for (const auto &[a, b] : E[L[w]].inc)
|
||||
E[C[b]].inc.insert({a, b});
|
||||
|
||||
for (const auto& [a, b] : E[L[w]].out)
|
||||
E[C[a]].out.insert({ a, b });
|
||||
for (const auto &[a, b] : E[L[w]].out)
|
||||
E[C[a]].out.insert({a, b});
|
||||
|
||||
for (const auto& [a, b] : E[L[w]].in) {
|
||||
for (const auto &[a, b] : E[L[w]].in) {
|
||||
if (C[a] == C[b]) {
|
||||
E[C[a]].in.insert({ a, b });
|
||||
}
|
||||
else {
|
||||
E[C[a]].out.insert({ a, b });
|
||||
E[C[b]].in.insert({ a, b });
|
||||
E[C[a]].in.insert({a, b});
|
||||
} else {
|
||||
E[C[a]].out.insert({a, b});
|
||||
E[C[b]].in.insert({a, b});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user