-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFlowEdge.h
169 lines (148 loc) · 3.9 KB
/
FlowEdge.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
//
// Created by Ryan.Zurrin001 on 1/14/2022.
//
#ifndef FLOWNETWORK_FLOWEDGE_H
#define FLOWNETWORK_FLOWEDGE_H
#include <bits/stdc++.h>
using namespace std;
#define FLOATING_POINT_EPSILON 1e-10
class FlowEdge {
public:
FlowEdge(int v, int w, double capacity);
FlowEdge(int v, int w, double capacity, double flow);
FlowEdge(FlowEdge& e);
FlowEdge(FlowEdge&& e);
FlowEdge& operator=(FlowEdge& e);
FlowEdge& operator=(FlowEdge&& e);
int from() const;
int to() const;
double capacity() const;
double flow() const;
int other(int vertex) const;
double residualCapacityTo(int vertex) const;
void addResidualFlowTo(int v, double delta);
string toString() const;
friend ostream& operator<<(ostream& os, const FlowEdge& e);
private:
int _v;
int _w;
double _capacity;
double _flow;
};
FlowEdge::FlowEdge(int v, int w, double capacity) {
if (v < 0 || w < 0) {
throw invalid_argument("vertex index must be nonnegative");
}
if (capacity < 0.0) {
throw invalid_argument("capacity must be nonnegative");
}
_v = v;
_w = w;
_capacity = capacity;
_flow = 0.0;
}
FlowEdge::FlowEdge(int v, int w, double capacity, double flow) {
if (v < 0 || w < 0) {
throw invalid_argument("vertex index must be nonnegative");
}
if (capacity < 0.0) {
throw invalid_argument("capacity must be nonnegative");
}
if (flow < 0.0 || flow > capacity) {
throw invalid_argument("flow must be nonnegative and less than or equal to capacity");
}
_v = v;
_w = w;
_capacity = capacity;
_flow = flow;
}
FlowEdge::FlowEdge(FlowEdge &e) {
_v = e._v;
_w = e._w;
_capacity = e._capacity;
_flow = e._flow;
}
FlowEdge::FlowEdge(FlowEdge &&e) {
_v = e._v;
_w = e._w;
_capacity = e._capacity;
_flow = e._flow;
}
FlowEdge &FlowEdge::operator=(FlowEdge &&e) {
if (this != &e) {
_v = e._v;
_w = e._w;
_capacity = e._capacity;
_flow = e._flow;
}
return *this;
}
FlowEdge &FlowEdge::operator=(FlowEdge &e) {
if (this != &e) {
_v = e._v;
_w = e._w;
_capacity = e._capacity;
_flow = e._flow;
}
return *this;
}
int FlowEdge::from() const {
return _v;
}
int FlowEdge::to() const {
return _w;
}
double FlowEdge::capacity() const {
return _capacity;
}
double FlowEdge::flow() const {
return _flow;
}
int FlowEdge::other(int vertex) const {
if (vertex == _v) return _w;
else if (vertex == _w) return _v;
else throw invalid_argument("invalid vertex");
}
double FlowEdge::residualCapacityTo(int vertex) const {
if (vertex == _v) return _flow;
else if (vertex == _w) return _capacity - _flow;
else throw invalid_argument("invalid vertex");
}
void FlowEdge::addResidualFlowTo(int v, double delta) {
if (delta < 0.0) {
throw invalid_argument("delta must be nonnegative");
}
if (v == _v) _flow -= delta;
else if (v == _w) _flow += delta;
else throw invalid_argument("invalid vertex");
if (abs(_flow) <= FLOATING_POINT_EPSILON) _flow = 0.0;
if (abs(_flow - _capacity) <= FLOATING_POINT_EPSILON) _flow = _capacity;
if (_flow < 0.0) {
throw invalid_argument("flow is negative");
}
if (_flow > _capacity) {
throw invalid_argument("flow exceeds capacity");
}
}
string FlowEdge::toString() const {
stringstream ss;
ss << _v << "->" << _w << " " << _flow << "/" << _capacity;
return ss.str();
}
ostream &operator<<(ostream &os, const FlowEdge &e) {
os << e.toString();
return os;
}
class CapacityComparator {
public:
bool operator()(const FlowEdge& e1, const FlowEdge& e2) const {
return e1.capacity() < e2.capacity();
}
};
class FlowComparator {
public:
bool operator()(const FlowEdge& e1, const FlowEdge& e2) const {
return e1.flow() < e2.flow();
}
};
#endif //FLOWNETWORK_FLOWEDGE_H