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

Commit cb70276

Browse files
committed
AllPairsShortestPaths.cpp
1 parent 4d7166b commit cb70276

File tree

3 files changed

+253
-2
lines changed

3 files changed

+253
-2
lines changed

AllPairsShortestPaths.cpp

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
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_AllPairsShortestPaths
22+
#endif
23+
24+
#ifndef FUNC_AllPairsShortestPaths
25+
#define FUNC_AllPairsShortestPaths
26+
27+
#include "utils.h"
28+
29+
#include "Graph.cpp"
30+
31+
template <typename T>
32+
Matrix<T> ExtendShortestPaths(Matrix<T>& L, Matrix<T>& W) {
33+
const size_t n = L.rows;
34+
Matrix<T> ans(n, n, T());
35+
for (size_t i = 0; i < n; i++)
36+
for (size_t j = 0; j < n; j++)
37+
for (size_t k = 0; k < n; k++)
38+
ans[i][j] = std::min(ans[i][j], L[i][k] + W[k][j]);
39+
return ans;
40+
}
41+
42+
template <typename T>
43+
Matrix<T> SlowAllPairsShortestPaths(Matrix<T>& W) {
44+
const size_t n = W.rows;
45+
Matrix<T> L = W;
46+
for (size_t m = 2; m < n; m++)
47+
L = ExtendShortestPaths(L, W);
48+
return L;
49+
}
50+
51+
template <typename T>
52+
Matrix<T> FasterAllPairsShortestPaths(Matrix<T>& W) {
53+
const size_t n = W.rows;
54+
Matrix<T> L = W;
55+
for (size_t m = 1; m < n - 1; m *= 2)
56+
L = ExtendShortestPaths(L, L);
57+
return L;
58+
}
59+
#endif
60+
61+
#ifdef MAIN_AllPairsShortestPaths
62+
int main(int argc, char *argv[]) {
63+
const size_t v = get_argv(argc, argv, 1, 5);
64+
const size_t e = get_argv(argc, argv, 2, 10);
65+
const bool dir = 1;
66+
const int weight_lower = get_argv<int>(argc, argv, 3, 0);
67+
const int weight_upper = get_argv<int>(argc, argv, 4, e);
68+
WeightedAdjMatrix<size_t, int> G(dir);
69+
G.random_graph(v, e, weight_lower, weight_upper);
70+
G.graphviz();
71+
std::cout << std::endl;
72+
Matrix<Weight<int>> W(v, v);
73+
G.to_matrix(W);
74+
Matrix<Weight<int>> ans1 = SlowAllPairsShortestPaths(W);
75+
std::cout << ans1 << std::endl;
76+
Matrix<Weight<int>> ans2 = FasterAllPairsShortestPaths(W);
77+
std::cout << ans2 << std::endl;
78+
std::cout << std::boolalpha << (ans1 == ans2) << std::endl;
79+
return 0;
80+
}
81+
#endif
82+

Graph.cpp

Lines changed: 168 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
#include <unordered_map>
3030
#include "utils.h"
3131

32+
#include "SquareMatrixMultiply.cpp"
33+
3234
#define uset typename std::unordered_set
3335
#define umap typename std::unordered_map
3436

@@ -67,6 +69,57 @@ struct EdgeHash {
6769
}
6870
};
6971

72+
template <typename T>
73+
class Weight {
74+
public:
75+
typedef T value_type;
76+
Weight(): inf(1) {}
77+
Weight(T x): val(x), inf(0) {}
78+
Weight(T x, int i): val(x), inf(i) {}
79+
bool operator<(const Weight<T>& rhs) const {
80+
if (inf || rhs.inf)
81+
return inf < rhs.inf;
82+
else
83+
return val < rhs.val;
84+
}
85+
bool operator==(const Weight<T>& rhs) const {
86+
if (inf || rhs.inf)
87+
return inf == rhs.inf;
88+
else
89+
return val == rhs.val;
90+
}
91+
Weight<T> operator+(const Weight<T>& rhs) const {
92+
if (inf + rhs.inf > 0)
93+
return Weight<T>(0, 1);
94+
if (inf + rhs.inf < 0)
95+
return Weight<T>(0, -1);
96+
assert(!inf && !rhs.inf);
97+
return Weight<T>(val + rhs.val);
98+
}
99+
Weight<T> operator-(const Weight<T>& rhs) const {
100+
if (inf - rhs.inf > 0)
101+
return Weight<T>(0, 1);
102+
if (inf - rhs.inf < 0)
103+
return Weight<T>(0, -1);
104+
assert(!inf && !rhs.inf);
105+
return Weight<T>(val - rhs.val);
106+
}
107+
friend std::ostream& operator<<(std::ostream& os, const Weight<T>& rhs){
108+
switch (rhs.inf) {
109+
case -1:
110+
return os << "-inf";
111+
case 0:
112+
return os << rhs.val;
113+
case 1:
114+
return os << "inf";
115+
default:
116+
return os;
117+
}
118+
}
119+
T val;
120+
int inf;
121+
};
122+
70123
template <typename T>
71124
class EdgeIteratorAL1 {
72125
public:
@@ -304,8 +357,103 @@ class GraphAdjMatrix: public Graph<T> {
304357
umap<T, umap<T, bool>> E;
305358
};
306359

360+
template <typename T, typename WT>
361+
class WeightedAdjMatrix {
362+
public:
363+
WeightedAdjMatrix(bool direction): dir(direction) {}
364+
bool add_vertex(T u) {
365+
if (V.find(u) != V.end())
366+
return false;
367+
V.insert(u);
368+
for (auto i = V.begin(); i != V.end(); i++) {
369+
const T& v = *i;
370+
if (u == v)
371+
E[u][u] = Weight<WT>(0);
372+
else
373+
E[u][v] = E[v][u] = Weight<WT>();
374+
}
375+
return true;
376+
}
377+
void add_edge(T s, T d, WT w) {
378+
add_vertex(s);
379+
if (s != d) {
380+
add_vertex(d);
381+
E[s][d] = w;
382+
if (!dir)
383+
E[d][s] = w;
384+
}
385+
}
386+
bool is_edge(T u, T v) {
387+
return u != v && !E[u][v].inf;
388+
}
389+
Weight<WT> get_edge(T u, T v) {
390+
return E[u][v];
391+
}
392+
void random_graph(T v, size_t e, WT l, WT h) {
393+
for (T i = 0; i < v; i++)
394+
add_vertex(i);
395+
std::vector<T> d;
396+
std::vector<WT> w;
397+
random_integers<T>(d, 0, v - 1, 2 * e);
398+
random_integers<WT>(w, l, h, e);
399+
for (size_t i = 0; i < e; i++)
400+
add_edge(d[2 * i], d[2 * i + 1], w[i]);
401+
}
402+
template <typename F1, typename F2>
403+
void graphviz(F1 f1, F2 f2) {
404+
if (dir)
405+
std::cout << "digraph G {" << std::endl;
406+
else
407+
std::cout << "graph G {" << std::endl;
408+
std::cout << '\t';
409+
for (auto i = V.begin(); i != V.end(); i++) {
410+
std::cout << *i;
411+
if (f1(*i))
412+
std::cout << "; \n\t";
413+
else
414+
std::cout << "; ";
415+
}
416+
std::cout << std::endl;
417+
for (auto i = E.begin(); i != E.end(); i++) {
418+
for (auto j = i->second.begin(); j != i->second.end(); j++) {
419+
if (i->first != j->first && !j->second.inf &&
420+
(dir || i->first < j->first)) {
421+
Edge<T> e(i->first, j->first, dir);
422+
std::cout << '\t' << e;
423+
std::cout << " [label=\"" << j->second << "\"";
424+
f2(e, j->second);
425+
std::cout << "]; " << std::endl;
426+
}
427+
}
428+
}
429+
std::cout << "}" << std::endl;
430+
}
431+
void graphviz() {
432+
auto f1 = [](T v) { return false; };
433+
auto f2 = [](Edge<T> e, Weight<WT> w) {};
434+
graphviz(f1, f2);
435+
}
436+
void to_matrix(Matrix<Weight<WT>>& ans) {
437+
const size_t n = V.size();
438+
for (size_t i = 0; i < n; i++)
439+
assert(V.find(i) != V.end());
440+
ans.cols = ans.rows = n;
441+
ans.data.reserve(n);
442+
for (size_t i = 0; i < n; i++) {
443+
MatrixRow<Weight<WT>> row;
444+
row.reserve(n);
445+
for (size_t j = 0; j < n; j++)
446+
row.push_back(E[i][j]);
447+
ans.data.push_back(row);
448+
}
449+
}
450+
bool dir;
451+
uset<T> V;
452+
umap<T, umap<T, Weight<WT>>> E;
453+
};
454+
307455
template <typename T>
308-
void random_graph(Graph<T>& G, T v, T e) {
456+
void random_graph(Graph<T>& G, T v, size_t e) {
309457
for (T i = 0; i < v; i++)
310458
G.add_vertex(i);
311459
std::vector<T> d;
@@ -315,7 +463,7 @@ void random_graph(Graph<T>& G, T v, T e) {
315463
}
316464

317465
template <typename T>
318-
void random_dag(Graph<T>& G, T v, T e) {
466+
void random_dag(Graph<T>& G, T v, size_t e) {
319467
for (T i = 0; i < v; i++)
320468
G.add_vertex(i);
321469
std::vector<T> d;
@@ -392,11 +540,29 @@ void graph_test(const size_t v, const size_t e) {
392540
}
393541
}
394542

543+
template <typename T, typename WT>
544+
void graph_weighted_test(const size_t v, const size_t e) {
545+
for (size_t dir = 0; dir <= 1; dir++) {
546+
WeightedAdjMatrix<T, WT> G(dir);
547+
G.random_graph(v, e, 1 - e, e);
548+
G.graphviz();
549+
std::cout << std::endl;
550+
Matrix<Weight<int>> M(v, v);
551+
G.to_matrix(M);
552+
std::cout << M;
553+
std::cout << std::endl;
554+
}
555+
}
556+
395557
int main(int argc, char *argv[]) {
396558
const size_t v = get_argv(argc, argv, 1, 5);
397559
const size_t e = get_argv(argc, argv, 2, 10);
560+
std::cout << "GraphAdjList" << std::endl;
398561
graph_test<GraphAdjList<size_t>>(v, e);
562+
std::cout << "GraphAdjMatrix" << std::endl;
399563
graph_test<GraphAdjMatrix<size_t>>(v, e);
564+
std::cout << "WeightedAdjMatrix" << std::endl;
565+
graph_weighted_test<size_t, int>(v, e);
400566
return 0;
401567
}
402568
#endif

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@
157157
| 24 | BellmanFord.cpp | Bellman Ford | 651 |
158158
| 24 | DagShortestPaths.cpp | Dag Shortest Paths | 655 |
159159
| 24 | Dijkstra.cpp | Dijkstra | 658 |
160+
| 25 | AllPairsShortestPaths.cpp | Extend Shortest Paths | 688 |
161+
| 25 | AllPairsShortestPaths.cpp | Slow All Pairs Shortest Paths | 689 |
162+
| 25 | AllPairsShortestPaths.cpp | Faster All Pairs Shortest Paths | 691 |
160163

161164
# Supplementary Files
162165
* `utils.h`: Utils

0 commit comments

Comments
 (0)