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

Commit 796003d

Browse files
committed
RelabelToFront.cpp
1 parent 0d4b36c commit 796003d

File tree

4 files changed

+190
-6
lines changed

4 files changed

+190
-6
lines changed

FordFulkerson.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ template <typename GT, typename T, typename WT>
3232
void FordFulkerson(GT& G, umap_WT& c, T s, T t, umap_WT& f) {
3333
for (auto i = G.all_edges(); !i.end(); i++)
3434
f[*i] = 0;
35-
auto get_c = [&G, &c, &f](T u, T v) mutable -> WT {
35+
auto cf = [&G, &c, &f](T u, T v) mutable -> WT {
3636
if (G.is_edge(u, v)) {
3737
Edge<T> e = Edge<T>(u, v, G.dir);
3838
return c[e] - f[e];
@@ -45,9 +45,9 @@ void FordFulkerson(GT& G, umap_WT& c, T s, T t, umap_WT& f) {
4545
GT Gf(G.dir);
4646
for (auto i = G.all_edges(); !i.end(); i++) {
4747
T u = i.s(), v = i.d();
48-
if (get_c(u, v))
48+
if (cf(u, v))
4949
Gf.add_edge(u, v);
50-
if (get_c(v, u))
50+
if (cf(v, u))
5151
Gf.add_edge(v, u);
5252
}
5353
umap<T, BFSInfo<T>> BFS_ans;
@@ -56,9 +56,9 @@ void FordFulkerson(GT& G, umap_WT& c, T s, T t, umap_WT& f) {
5656
PrintPath(s, t, BFS_ans, p);
5757
if (!p.size())
5858
break;
59-
WT cfp = get_c(p[0], p[1]);
59+
WT cfp = cf(p[0], p[1]);
6060
for (size_t i = 2; i < p.size(); i++)
61-
cfp = std::min(cfp, get_c(p[i - 1], p[i]));
61+
cfp = std::min(cfp, cf(p[i - 1], p[i]));
6262
for (size_t i = 1; i < p.size(); i++) {
6363
if (G.is_edge(p[i - 1], p[i]))
6464
f[Edge<T>(p[i - 1], p[i], G.dir)] += cfp;
@@ -77,7 +77,7 @@ int main(int argc, char *argv[]) {
7777
const int weight_lower = get_argv<int>(argc, argv, 3, 0);
7878
const int weight_upper = get_argv<int>(argc, argv, 4, e);
7979
GraphAdjList<size_t> G(dir);
80-
random_graph(G, v, e);
80+
random_flow(G, v, e);
8181
umap<Edge<size_t>, int, EdgeHash<size_t>> c;
8282
random_weight(G, c, weight_lower, weight_upper);
8383
umap<Edge<size_t>, int, EdgeHash<size_t>> f;

Graph.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,20 @@ void random_dag(Graph<T>& G, T v, size_t e) {
496496
}
497497
}
498498

499+
template <typename T>
500+
void random_flow(Graph<T>& G, T v, size_t e) {
501+
// disables (u, v) and (v, u)
502+
for (T i = 0; i < v; i++)
503+
G.add_vertex(i);
504+
std::vector<T> d;
505+
random_integers<T>(d, 0, v - 1, 2 * e);
506+
for (size_t i = 0; i < e; i++) {
507+
T a = d[2 * i], b = d[2 * i + 1];
508+
if (a != b && !G.is_edge(a, b) && !G.is_edge(b, a))
509+
G.add_edge(a, b);
510+
}
511+
}
512+
499513
template <typename WT, typename T, typename GT>
500514
void random_weight(GT& G, umap_WT& w, WT l, WT u) {
501515
std::random_device rd;

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@
166166
| 25 | Johnson.cpp | Johnson | 704 |
167167
| 26 | FordFulkerson.cpp | Ford Fulkerson | 724 |
168168
| 26 | MaximumBipartiteMatching.cpp | Maximum Bipartite Matching | 733 |
169+
| 26 | RelabelToFront.cpp | Push | 739 |
170+
| 26 | RelabelToFront.cpp | Relabel | 740 |
171+
| 26 | RelabelToFront.cpp | Initialize Preflow | 740 |
172+
| 26 | RelabelToFront.cpp | Discharge | 751 |
173+
| 26 | RelabelToFront.cpp | Relabel To Front | 755 |
169174

170175
# Supplementary Files
171176
* `utils.h`: Utils

RelabelToFront.cpp

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
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_RelabelToFront
22+
#endif
23+
24+
#ifndef FUNC_RelabelToFront
25+
#define FUNC_RelabelToFront
26+
27+
#include <list>
28+
#include "utils.h"
29+
30+
#include "Graph.cpp"
31+
32+
#define list_T typename std::list<T>
33+
34+
template <typename GT, typename T, typename WT>
35+
WT cf(GT& G, umap_WT& c, umap_WT& f, T u, T v) {
36+
if (G.is_edge(u, v)) {
37+
Edge<T> e = Edge<T>(u, v, G.dir);
38+
return c[e] - f[e];
39+
} else if (G.is_edge(v, u))
40+
return f[Edge<T>(v, u, G.dir)];
41+
else
42+
return 0;
43+
};
44+
45+
template <typename GT, typename T, typename WT>
46+
void Push(GT& G, umap_WT& c, umap_WT& f, umap<T, WT>& e, T u, T v) {
47+
WT delta = std::min(e[u], cf(G, c, f, u, v));
48+
if (G.is_edge(u, v))
49+
f[Edge<T>(u, v, G.dir)] += delta;
50+
else
51+
f[Edge<T>(v, u, G.dir)] -= delta;
52+
e[u] -= delta;
53+
e[v] += delta;
54+
}
55+
56+
template <typename GT, typename T, typename WT>
57+
void Relabel(GT& G, umap_WT& c, umap_WT& f, umap<T, list_T>& N, umap<T, T>& h,
58+
T u) {
59+
Weight<T> min_h;
60+
for (auto i = N[u].begin(); i != N[u].end(); i++)
61+
if (cf(G, c, f, u, *i))
62+
min_h = std::min(min_h, Weight<T>(h[*i]));
63+
assert(!min_h.inf);
64+
h[u] = 1 + min_h.val;
65+
}
66+
67+
template <typename GT, typename T, typename WT>
68+
void InitializePreflow(GT& G, umap_WT& c, umap_WT& f, umap<T, WT>& e,
69+
umap<T, T>& h, T s) {
70+
for (auto i = G.V.begin(); i != G.V.end(); i++) {
71+
const T& v = *i;
72+
h[v] = 0;
73+
e[v] = 0;
74+
}
75+
for (auto i = G.all_edges(); !i.end(); i++)
76+
f[*i] = 0;
77+
h[s] = G.V.size();
78+
for (auto i = G.edges_from(s); !i.end(); i++) {
79+
f[*i] = c[*i];
80+
e[i.d()] = c[*i];
81+
e[s] -= c[*i];
82+
}
83+
}
84+
85+
template <typename GT, typename T, typename WT>
86+
void Discharge(GT& G, umap_WT& c, umap_WT& f, umap<T, WT>& e,
87+
umap<T, list_T>& N, umap<T, T>& h, umap<T, list_T::iterator>& cur, T u) {
88+
while (e[u]) {
89+
if (cur[u] == N[u].end()) {
90+
Relabel(G, c, f, N, h, u);
91+
cur[u] = N[u].begin();
92+
} else if (cf(G, c, f, u, *(cur[u])) && h[u] == h[*(cur[u])] + 1)
93+
Push(G, c, f, e, u, *(cur[u]));
94+
else
95+
cur[u]++;
96+
}
97+
}
98+
99+
template <typename GT, typename T, typename WT>
100+
void RelabelToFront(GT& G, umap_WT& c, T s, T t, umap_WT& f) {
101+
umap<T, WT> e;
102+
umap<T, T> h;
103+
umap<T, list_T> N;
104+
umap<T, list_T::iterator> cur;
105+
list_T L;
106+
InitializePreflow(G, c, f, e, h, s);
107+
for (auto i = G.all_edges(); !i.end(); i++) {
108+
T u = i.s(), v = i.d();
109+
if (u != s && u != t)
110+
N[u].push_back(v);
111+
if (v != s && v != t)
112+
N[v].push_back(u);
113+
}
114+
for (auto i = G.V.begin(); i != G.V.end(); i++) {
115+
T u = *i;
116+
if (u != s && u != t) {
117+
cur[u] = N[u].begin();
118+
L.push_back(u);
119+
}
120+
}
121+
for (auto i = L.begin(); i != L.end(); i++) {
122+
T u = *i;
123+
T old_height = h[u];
124+
Discharge(G, c, f, e, N, h, cur, u);
125+
if (h[u] > old_height) {
126+
L.erase(i);
127+
L.push_front(u);
128+
i = L.begin();
129+
}
130+
}
131+
}
132+
#endif
133+
134+
#ifdef MAIN_RelabelToFront
135+
int main(int argc, char *argv[]) {
136+
const size_t v = get_argv(argc, argv, 1, 5);
137+
const size_t e = get_argv(argc, argv, 2, 10);
138+
const bool dir = true;
139+
const int weight_lower = get_argv<int>(argc, argv, 3, 0);
140+
const int weight_upper = get_argv<int>(argc, argv, 4, e);
141+
GraphAdjList<size_t> G(dir);
142+
random_flow(G, v, e);
143+
umap<Edge<size_t>, int, EdgeHash<size_t>> c;
144+
random_weight(G, c, weight_lower, weight_upper);
145+
umap<Edge<size_t>, int, EdgeHash<size_t>> f;
146+
for (auto i = G.all_edges(); !i.end(); i++)
147+
if (i.s() == i.d())
148+
c[*i] = 0;
149+
RelabelToFront(G, c, 0ul, v - 1ul, f);
150+
auto f1 = [v](size_t vv) {
151+
if (vv == v - 1 || vv == 0)
152+
std::cout << " [style=bold]";
153+
return false;
154+
};
155+
auto f2 = [c, f](Edge<size_t> e) mutable {
156+
std::cout << " [label=\"" << f[e] << "/" << c[e] << "\"";
157+
if (f[e])
158+
std::cout << " style=bold";
159+
std::cout << "]";
160+
};
161+
graphviz(G, f1, f2);
162+
return 0;
163+
}
164+
#endif
165+

0 commit comments

Comments
 (0)