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

Commit e39a4ff

Browse files
committed
DFS.cpp
1 parent 8f01c88 commit e39a4ff

File tree

4 files changed

+205
-11
lines changed

4 files changed

+205
-11
lines changed

BFS.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,10 @@ int main(int argc, char *argv[]) {
109109
std::cout << "d = INF";
110110
else
111111
std::cout << "d = " << i.d << "; pi = " << i.pi;
112-
std::cout << "\"";
113-
std::cout << "]";
112+
std::cout << "\"]";
114113
return true;
115114
};
116-
auto f2 = [dir](Edge<size_t> e) {};
115+
auto f2 = [](Edge<size_t> e) {};
117116
graphviz(G, f1, f2);
118117
for (auto i = G.V.begin(); i != G.V.end(); i++) {
119118
std::vector<size_t> ans;

DFS.cpp

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
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_DFS
22+
#endif
23+
24+
#ifndef FUNC_DFS
25+
#define FUNC_DFS
26+
27+
#include "utils.h"
28+
29+
#include "Graph.cpp"
30+
31+
const size_t INF = -1;
32+
33+
enum DFSColor { white, gray, black };
34+
35+
enum DFSEdgeType { tree, back, forward, cross };
36+
37+
template <typename T>
38+
class DFSInfo {
39+
public:
40+
DFSInfo(): color(white), d(INF), f(INF), pi_exist(false) {}
41+
void set_color(DFSColor c, size_t& time) {
42+
color = c;
43+
switch (color) {
44+
case white:
45+
break;
46+
case gray:
47+
d = time++;
48+
break;
49+
case black:
50+
f = time++;
51+
break;
52+
}
53+
}
54+
void set_pi(T p) {
55+
pi = p;
56+
pi_exist = true;
57+
}
58+
enum DFSColor color;
59+
size_t d, f;
60+
T pi;
61+
bool pi_exist;
62+
};
63+
64+
std::ostream& operator<<(std::ostream& os, const DFSEdgeType& rhs) {
65+
switch (rhs) {
66+
case tree:
67+
return os << "T";
68+
case back:
69+
return os << "B";
70+
case forward:
71+
return os << "F";
72+
case cross:
73+
return os << "C";
74+
default:
75+
return os;
76+
}
77+
}
78+
79+
template <typename T>
80+
bool is_ancestor(umap<T, DFSInfo<T>>& ans, T u, T v) {
81+
if (u == v)
82+
return true;
83+
DFSInfo<T>& info = ans[v];
84+
if (info.pi_exist)
85+
return is_ancestor(ans, u, info.pi);
86+
else
87+
return false;
88+
}
89+
90+
template <typename GT, typename T, typename VT, typename ET>
91+
void DFSVisit(GT& G, VT& ans, ET& edge_ans, T u, size_t& time) {
92+
DFSInfo<T>& info = ans[u];
93+
info.set_color(gray, time);
94+
for (auto i = G.edges_from(u); !i.end(); i++) {
95+
T v = i.d();
96+
DFSInfo<T>& vinfo = ans[v];
97+
switch (vinfo.color) {
98+
case white:
99+
edge_ans[*i] = tree;
100+
vinfo.set_pi(u);
101+
DFSVisit(G, ans, edge_ans, v, time);
102+
break;
103+
case gray:
104+
edge_ans[*i] = back;
105+
break;
106+
case black:
107+
if (is_ancestor(ans, u, v))
108+
edge_ans[*i] = forward;
109+
else
110+
edge_ans[*i] = cross;
111+
break;
112+
}
113+
}
114+
info.set_color(black, time);
115+
}
116+
117+
template <typename GT, typename VT, typename ET>
118+
void DFS(GT& G, VT& ans, ET& edge_ans) {
119+
using T = typename GT::vertix_type;
120+
for (auto i = G.V.begin(); i != G.V.end(); i++)
121+
ans[*i] = DFSInfo<T>();
122+
size_t time = 0;
123+
for (auto i = G.V.begin(); i != G.V.end(); i++)
124+
if (ans[*i].color == white)
125+
DFSVisit(G, ans, edge_ans, *i, time);
126+
if (!G.dir)
127+
for (auto i = G.all_edges(); !i.end(); i++)
128+
if (i.s() < i.d()) {
129+
Edge<T> j = (*i).reverse();
130+
if (edge_ans[*i] != edge_ans[j]) {
131+
edge_ans[j] = std::min(edge_ans[*i], edge_ans[j]);
132+
edge_ans[*i] = edge_ans[j];
133+
}
134+
}
135+
}
136+
#endif
137+
138+
#ifdef MAIN_DFS
139+
int main(int argc, char *argv[]) {
140+
const size_t v = get_argv(argc, argv, 1, 5);
141+
const size_t e = get_argv(argc, argv, 2, 10);
142+
const bool dir = get_argv(argc, argv, 3, 0);
143+
GraphAdjList<size_t> G(dir);
144+
random_graph(G, v, e);
145+
umap<size_t, DFSInfo<size_t>> inf;
146+
umap<Edge<size_t>, DFSEdgeType, EdgeHash<size_t>> edge_inf;
147+
DFS(G, inf, edge_inf);
148+
auto f1 = [inf](size_t v) mutable {
149+
DFSInfo<size_t>& i = inf[v];
150+
std::cout << " [";
151+
switch (i.color) {
152+
case white:
153+
break;
154+
case black:
155+
std::cout << "color=black style=filled fontcolor=white ";
156+
break;
157+
case gray:
158+
std::cout << "color=gray style=filled ";
159+
break;
160+
}
161+
std::cout << "label=\"" << v << "\\n";
162+
std::cout << "d = " << i.d << "; f = " << i.f;
163+
if (i.pi_exist)
164+
std::cout << "; pi = " << i.pi;
165+
std::cout << "\"]";
166+
return true;
167+
};
168+
auto f2 = [edge_inf](Edge<size_t> e) mutable {
169+
std::cout << " [" << "label=\"" << edge_inf[e] << "\"]";
170+
};
171+
graphviz(G, f1, f2);
172+
return 0;
173+
}
174+
#endif
175+

Graph.cpp

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,29 @@ class Edge {
4141
else
4242
return os << rhs.s << " -- " << rhs.d;
4343
}
44+
bool operator==(const Edge& rhs) const {
45+
return dir == rhs.dir && s == rhs.s && d == rhs.d;
46+
}
47+
Edge<T> reverse() const {
48+
return Edge<T>(d, s, dir);
49+
}
4450
T s, d;
4551
bool dir;
4652
};
4753

54+
template <typename T>
55+
struct EdgeHash {
56+
std::size_t operator()(Edge<T> t) const
57+
{
58+
size_t shift = sizeof(size_t) * 4;
59+
size_t a = std::hash<T>()(t.s);
60+
size_t b = std::hash<T>()(t.d);
61+
size_t B = b >> shift | b << shift;
62+
size_t C = t.dir << (shift - 1);
63+
return a ^ B ^ C;
64+
}
65+
};
66+
4867
template <typename T>
4968
class EdgeIteratorAL1 {
5069
public:
@@ -62,7 +81,7 @@ class EdgeIteratorAL1 {
6281
}
6382
void next() {
6483
if (mbegin != mend)
65-
while (sbegin == send || s() > d()) {
84+
while (sbegin == send || (!dir && s() > d())) {
6685
if (sbegin == send) {
6786
mbegin++;
6887
if (mbegin == mend)
@@ -128,7 +147,7 @@ class EdgeIteratorAM1 {
128147
}
129148
void next() {
130149
if (mbegin != mend)
131-
while (sbegin == send || !sbegin->second || s() > d()) {
150+
while (sbegin == send || !sbegin->second || !dir && s() > d()) {
132151
if (sbegin == send) {
133152
mbegin++;
134153
if (mbegin == mend)
@@ -287,12 +306,11 @@ void graphviz(T& G, F1 f1, F2 f2) {
287306
std::cout << "; ";
288307
}
289308
std::cout << std::endl;
290-
for (auto i = G.all_edges(); !i.end(); i++)
291-
if (G.dir || i.s() < i.d()) {
292-
std::cout << '\t' << *i;
293-
f2(*i);
294-
std::cout << "; " << std::endl;
295-
}
309+
for (auto i = G.all_edges(); !i.end(); i++) {
310+
std::cout << '\t' << *i;
311+
f2(*i);
312+
std::cout << "; " << std::endl;
313+
}
296314
std::cout << "}" << std::endl;
297315
}
298316

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@
146146
| 21 | DisjointSet.cpp | Find Set | 571 |
147147
| 22 | BFS.cpp | BFS | 595 |
148148
| 22 | BFS.cpp | Print Path | 601 |
149+
| 22 | DFS.cpp | DFS | 604 |
150+
| 22 | DFS.cpp | DFS Visit | 604 |
149151

150152
# Supplementary Files
151153
* `utils.h`: Utils

0 commit comments

Comments
 (0)