Skip to content
This repository was archived by the owner on Nov 29, 2020. It is now read-only.

Commit b688580

Browse files
committed
SCC.cpp
1 parent 9451073 commit b688580

File tree

6 files changed

+137
-15
lines changed

6 files changed

+137
-15
lines changed

BFS.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
#ifndef FUNC_BFS
2525
#define FUNC_BFS
2626

27-
#include <cassert>
2827
#include "utils.h"
2928

3029
#include "Queue.cpp"

DFS.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,8 @@ void DFSVisit(GT& G, VT& ans, ET edge_ans, T u, size_t& time) {
118118
info.set_color(black, time);
119119
}
120120

121-
template <typename GT, typename VT, typename ET>
122-
void DFS(GT& G, VT& ans, ET edge_ans) {
123-
using T = typename GT::vertix_type;
121+
template <typename T, typename GT, typename VT>
122+
void DFS(GT& G, VT& ans, umap<Edge<T>, DFSEdgeType, EdgeHash<T>>* edge_ans) {
124123
for (auto i = G.V.begin(); i != G.V.end(); i++)
125124
ans[*i] = DFSInfo<T>();
126125
size_t time = 0;

DisjointSet.cpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,22 @@
2424
#ifndef FUNC_DisjointSet
2525
#define FUNC_DisjointSet
2626

27+
#include <map>
2728
#include "utils.h"
2829

2930
#include "Graph.cpp"
3031

3132
const size_t NIL = -1;
3233

34+
template <typename T>
3335
class DisjointSetForest {
3436
public:
35-
DisjointSetForest(size_t n): p(n, NIL), rank(n, 0) {}
36-
void MakeSet(size_t x) {
37+
DisjointSetForest() {}
38+
void MakeSet(T x) {
3739
p[x] = x;
3840
rank[x] = 0;
3941
}
40-
void Link(size_t x, size_t y) {
42+
void Link(T x, T y) {
4143
if (rank[x] > rank[y])
4244
p[y] = x;
4345
else {
@@ -46,32 +48,34 @@ class DisjointSetForest {
4648
rank[y]++;
4749
}
4850
}
49-
size_t FindSet(size_t x) {
51+
T FindSet(T x) {
5052
if (p[x] == NIL)
5153
return x;
5254
if (x != p[x])
5355
p[x] = FindSet(p[x]);
5456
return p[x];
5557
}
56-
void Union(size_t x, size_t y) {
58+
void Union(T x, T y) {
5759
Link(FindSet(x), FindSet(y));
5860
}
59-
std::vector<size_t> p, rank;
61+
std::map<T, T> p;
62+
std::map<T, size_t> rank;
6063
};
6164

65+
template <typename T>
6266
class ConnectedComponents {
6367
public:
64-
ConnectedComponents(size_t n, GraphAdjList<size_t>& G): F(n) {
68+
ConnectedComponents(T n, GraphAdjList<T>& G) {
6569
for (auto i = G.V.begin(); i != G.V.end(); i++)
6670
F.MakeSet(*i);
6771
for (auto i = G.all_edges(); !i.end(); i++)
6872
if (F.FindSet(i.s()) != F.FindSet(i.d()))
6973
F.Union(i.s(), i.d());
7074
}
71-
bool SameComponent(size_t u, size_t v) {
75+
bool SameComponent(T u, T v) {
7276
return F.FindSet(u) == F.FindSet(v);
7377
}
74-
DisjointSetForest F;
78+
DisjointSetForest<T> F;
7579
};
7680
#endif
7781

@@ -86,7 +90,7 @@ int main(int argc, char *argv[]) {
8690
GraphAdjList<size_t> G(false);
8791
random_graph(G, v, e);
8892
graphviz(G);
89-
ConnectedComponents CC(n, G);
93+
ConnectedComponents<size_t> CC(n, G);
9094
for (size_t i = 0; i < n; i++) {
9195
std::cout << c[i] << "\t" << d[i] << "\tconnected = " << std::boolalpha;
9296
std::cout << CC.SameComponent(c[i], d[i]) << std::endl;

Graph.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#ifndef FUNC_Graph
2525
#define FUNC_Graph
2626

27+
#include <cassert>
2728
#include <unordered_set>
2829
#include <unordered_map>
2930
#include "utils.h"
@@ -147,7 +148,7 @@ class EdgeIteratorAM1 {
147148
}
148149
void next() {
149150
if (mbegin != mend)
150-
while (sbegin == send || !sbegin->second || !dir && s() > d()) {
151+
while (sbegin == send || !sbegin->second || (!dir && s()>d())) {
151152
if (sbegin == send) {
152153
mbegin++;
153154
if (mbegin == mend)
@@ -217,6 +218,7 @@ class Graph {
217218
}
218219
virtual void add_edge(T, T) = 0;
219220
virtual bool is_edge(T u, T v) = 0;
221+
virtual void transpose() = 0;
220222
virtual ~Graph() {}
221223
typedef T vertix_type;
222224
bool dir;
@@ -243,6 +245,14 @@ class GraphAdjList: public Graph<T> {
243245
EdgeIteratorAL2<T> edges_from(T s) {
244246
return EdgeIteratorAL2<T>(s, E[s], this->dir);
245247
}
248+
virtual void transpose() {
249+
assert(this->dir);
250+
umap<T, uset<T>> old_E = E;
251+
E.clear();
252+
for (auto i = old_E.begin(); i != old_E.end(); i++)
253+
for (auto j = i->second.begin(); j != i->second.end(); j++)
254+
E[*j].insert(i->first);
255+
}
246256
virtual ~GraphAdjList() {}
247257
umap<T, uset<T>> E;
248258
};
@@ -277,6 +287,13 @@ class GraphAdjMatrix: public Graph<T> {
277287
EdgeIteratorAM2<T> edges_from(T s) {
278288
return EdgeIteratorAM2<T>(s, E[s], this->dir);
279289
}
290+
virtual void transpose() {
291+
assert(this->dir);
292+
for (auto i = this->V.begin(); i != this->V.end(); i++)
293+
for (auto j = this->V.begin(); j != this->V.end(); j++)
294+
if (*i < *j)
295+
std::swap(E[*i][*j], E[*j][*i]);
296+
}
280297
virtual ~GraphAdjMatrix() {}
281298
umap<T, umap<T, bool>> E;
282299
};
@@ -338,6 +355,10 @@ void graph_test(const size_t v, const size_t e) {
338355
}
339356
std::cout << std::endl;
340357
graphviz(G);
358+
if (dir) {
359+
G.transpose();
360+
graphviz(G);
361+
}
341362
std::cout << std::endl;
342363
}
343364
}

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@
149149
| 22 | DFS.cpp | DFS | 604 |
150150
| 22 | DFS.cpp | DFS Visit | 604 |
151151
| 22 | TopologicalSort.cpp | Topological Sort | 613 |
152+
| 23 | SCC.cpp | Strongly Connected Components | 617 |
152153

153154
# Supplementary Files
154155
* `utils.h`: Utils

SCC.cpp

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
//
2+
// algorithm - some algorithms in "Introduction to Algorithms", third edition
3+
// Copyright (C) 2018 lxylxy123456
4+
//
5+
// This program is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU Affero General Public License as
7+
// published by the Free Software Foundation, either version 3 of the
8+
// License, or (at your option) any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU Affero General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU Affero General Public License
16+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
//
18+
19+
#ifndef MAIN
20+
#define MAIN
21+
#define MAIN_SCC
22+
#endif
23+
24+
#ifndef FUNC_SCC
25+
#define FUNC_SCC
26+
27+
#include <map>
28+
#include "utils.h"
29+
30+
#include "DFS.cpp"
31+
#include "DisjointSet.cpp"
32+
33+
template <typename GT, typename T, typename VT>
34+
void DFSVisit_SCC(GT& G, VT& inf, DisjointSetForest<T>& D, T u, size_t& time) {
35+
DFSInfo<T>& info = inf[u];
36+
info.set_color(gray, time);
37+
for (auto i = G.edges_from(u); !i.end(); i++) {
38+
T v = i.d();
39+
DFSInfo<T>& vinfo = inf[v];
40+
if (vinfo.color == white) {
41+
vinfo.set_pi(u);
42+
D.Union(u, v);
43+
DFSVisit_SCC(G, inf, D, v, time);
44+
}
45+
}
46+
info.set_color(black, time);
47+
}
48+
49+
template <typename GT, typename T>
50+
void DFS_SCC(GT& G, std::map<size_t, T>& f_order, DisjointSetForest<T>& D) {
51+
umap<T, DFSInfo<T>> inf;
52+
for (auto i = G.V.begin(); i != G.V.end(); i++)
53+
inf[*i] = DFSInfo<T>();
54+
size_t time = 0;
55+
for (auto i = f_order.rbegin(); i != f_order.rend(); i++) {
56+
T v = i->second;
57+
if (inf[v].color == white)
58+
DFSVisit_SCC(G, inf, D, v, time);
59+
}
60+
}
61+
62+
template <typename GT, typename T>
63+
void StronglyConnectedComponents(GT& G, DisjointSetForest<T>& D) {
64+
umap<T, DFSInfo<T>> inf;
65+
DFS<T>(G, inf, nullptr);
66+
GT G_transpose = G;
67+
G_transpose.transpose();
68+
std::map<size_t, T> f_order;
69+
for (auto i = inf.begin(); i != inf.end(); i++) {
70+
f_order[i->second.f] = i->first;
71+
D.MakeSet(i->first);
72+
}
73+
DFS_SCC(G_transpose, f_order, D);
74+
}
75+
#endif
76+
77+
#ifdef MAIN_SCC
78+
int main(int argc, char *argv[]) {
79+
const size_t v = get_argv(argc, argv, 1, 5);
80+
const size_t e = get_argv(argc, argv, 2, 10);
81+
const bool dir = get_argv(argc, argv, 3, 1);
82+
GraphAdjList<size_t> G(dir);
83+
random_graph(G, v, e);
84+
DisjointSetForest<size_t> ans;
85+
StronglyConnectedComponents(G, ans);
86+
auto f1 = [](size_t v) { return false; };
87+
auto f2 = [](Edge<size_t> e) {};
88+
graphviz(G, f1, f2);
89+
// print ans
90+
std::map<size_t, uset<size_t>> components;
91+
for (auto i = G.V.begin(); i != G.V.end(); i++)
92+
components[ans.FindSet(*i)].insert(*i);
93+
for (auto i = components.begin(); i != components.end(); i++)
94+
output_integers(i->second);
95+
return 0;
96+
}
97+
#endif
98+

0 commit comments

Comments
 (0)