marci@9
|
1 |
#ifndef MARCI_MAX_FLOW_HH
|
marci@9
|
2 |
#define MARCI_MAX_FLOW_HH
|
marci@9
|
3 |
|
marci@9
|
4 |
#include <algorithm>
|
marci@9
|
5 |
|
marci@9
|
6 |
#include <marci_property_vector.hh>
|
marci@9
|
7 |
#include <marci_bfs.hh>
|
marci@9
|
8 |
|
marci@9
|
9 |
namespace marci {
|
marci@9
|
10 |
|
marci@9
|
11 |
template<typename graph_type, typename T>
|
marci@9
|
12 |
class res_graph_type {
|
marci@19
|
13 |
typedef typename graph_type::node_iterator node_iterator;
|
marci@19
|
14 |
typedef typename graph_type::each_node_iterator each_node_iterator;
|
marci@19
|
15 |
typedef typename graph_type::sym_edge_iterator old_sym_edge_iterator;
|
marci@9
|
16 |
graph_type& G;
|
marci@9
|
17 |
edge_property_vector<graph_type, T>& flow;
|
marci@9
|
18 |
edge_property_vector<graph_type, T>& capacity;
|
marci@9
|
19 |
public:
|
marci@9
|
20 |
res_graph_type(graph_type& _G, edge_property_vector<graph_type, T>& _flow, edge_property_vector<graph_type, T>& _capacity) : G(_G), flow(_flow), capacity(_capacity) { }
|
marci@9
|
21 |
|
marci@19
|
22 |
class edge_iterator {
|
marci@9
|
23 |
friend class res_graph_type<graph_type, T>;
|
marci@9
|
24 |
protected:
|
marci@9
|
25 |
res_graph_type<graph_type, T>* resG;
|
marci@19
|
26 |
old_sym_edge_iterator sym;
|
marci@9
|
27 |
public:
|
marci@19
|
28 |
edge_iterator() { }
|
marci@9
|
29 |
//bool is_free() {
|
marci@9
|
30 |
//if (resG->G.a_node(sym)==resG->G.tail(sym)) {
|
marci@9
|
31 |
// return (resG->flow.get(sym)<resG->capacity.get(sym));
|
marci@9
|
32 |
//} else {
|
marci@9
|
33 |
// return (resG->flow.get(sym)>0);
|
marci@9
|
34 |
//}
|
marci@9
|
35 |
//}
|
marci@9
|
36 |
T free() {
|
marci@9
|
37 |
if (resG->G.a_node(sym)==resG->G.tail(sym)) {
|
marci@9
|
38 |
return (resG->capacity.get(sym)-resG->flow.get(sym));
|
marci@9
|
39 |
} else {
|
marci@9
|
40 |
return (resG->flow.get(sym));
|
marci@9
|
41 |
}
|
marci@9
|
42 |
}
|
marci@19
|
43 |
bool valid() { return sym.valid(); }
|
marci@17
|
44 |
void make_invalid() { sym.make_invalid(); }
|
marci@9
|
45 |
void augment(T a) {
|
marci@9
|
46 |
if (resG->G.a_node(sym)==resG->G.tail(sym)) {
|
marci@9
|
47 |
resG->flow.put(sym, resG->flow.get(sym)+a);
|
marci@9
|
48 |
} else {
|
marci@9
|
49 |
resG->flow.put(sym, resG->flow.get(sym)-a);
|
marci@9
|
50 |
}
|
marci@9
|
51 |
}
|
marci@9
|
52 |
};
|
marci@9
|
53 |
|
marci@19
|
54 |
class out_edge_iterator : public edge_iterator {
|
marci@9
|
55 |
public:
|
marci@19
|
56 |
out_edge_iterator() { }
|
marci@19
|
57 |
out_edge_iterator(res_graph_type<graph_type, T>& _resG, const node_iterator& v) {
|
marci@9
|
58 |
resG=&_resG;
|
marci@9
|
59 |
sym=resG->G.first_sym_edge(v);
|
marci@19
|
60 |
while( sym.valid() && !(free()>0) ) { ++sym; }
|
marci@9
|
61 |
}
|
marci@19
|
62 |
out_edge_iterator& operator++() {
|
marci@9
|
63 |
++sym;
|
marci@19
|
64 |
while( sym.valid() && !(free()>0) ) { ++sym; }
|
marci@9
|
65 |
return *this;
|
marci@9
|
66 |
}
|
marci@9
|
67 |
};
|
marci@9
|
68 |
|
marci@19
|
69 |
out_edge_iterator first_out_edge(const node_iterator& v) {
|
marci@19
|
70 |
return out_edge_iterator(*this, v);
|
marci@9
|
71 |
}
|
marci@9
|
72 |
|
marci@9
|
73 |
each_node_iterator first_node() {
|
marci@9
|
74 |
return G.first_node();
|
marci@9
|
75 |
}
|
marci@9
|
76 |
|
marci@19
|
77 |
node_iterator tail(const edge_iterator& e) { return G.a_node(e.sym); }
|
marci@19
|
78 |
node_iterator head(const edge_iterator& e) { return G.b_node(e.sym); }
|
marci@9
|
79 |
|
marci@9
|
80 |
int id(const node_iterator& v) { return G.id(v); }
|
marci@9
|
81 |
|
marci@17
|
82 |
//node_iterator invalid_node() { return G.invalid_node(); }
|
marci@19
|
83 |
//res_edge_it invalid_edge() { res_edge_it n; n.sym=G.invalid_sym_edge(); return n; }
|
marci@9
|
84 |
};
|
marci@9
|
85 |
|
marci@9
|
86 |
template <typename graph_type, typename T>
|
marci@9
|
87 |
struct max_flow_type {
|
marci@19
|
88 |
typedef typename graph_type::node_iterator node_iterator;
|
marci@19
|
89 |
typedef typename graph_type::edge_iterator edge_iterator;
|
marci@19
|
90 |
typedef typename graph_type::each_node_iterator each_node_iterator;
|
marci@19
|
91 |
typedef typename graph_type::out_edge_iterator out_edge_iterator;
|
marci@19
|
92 |
typedef typename graph_type::in_edge_iterator in_edge_iterator;
|
marci@9
|
93 |
graph_type& G;
|
marci@9
|
94 |
node_iterator s;
|
marci@9
|
95 |
node_iterator t;
|
marci@9
|
96 |
edge_property_vector<graph_type, T> flow;
|
marci@9
|
97 |
edge_property_vector<graph_type, T>& capacity;
|
marci@9
|
98 |
|
marci@9
|
99 |
max_flow_type(graph_type& _G, node_iterator _s, node_iterator _t, edge_property_vector<graph_type, T>& _capacity) : G(_G), s(_s), t(_t), flow(_G), capacity(_capacity) {
|
marci@19
|
100 |
for(each_node_iterator i=G.first_node(); i.valid(); ++i)
|
marci@19
|
101 |
for(out_edge_iterator j=G.first_out_edge(i); j.valid(); ++j)
|
marci@9
|
102 |
flow.put(j, 0);
|
marci@9
|
103 |
}
|
marci@9
|
104 |
void run() {
|
marci@9
|
105 |
typedef res_graph_type<graph_type, T> aug_graph_type;
|
marci@9
|
106 |
aug_graph_type res_graph(G, flow, capacity);
|
marci@9
|
107 |
|
marci@9
|
108 |
bool augment;
|
marci@9
|
109 |
do {
|
marci@9
|
110 |
augment=false;
|
marci@14
|
111 |
|
marci@19
|
112 |
typedef std::queue<aug_graph_type::out_edge_iterator> bfs_queue_type;
|
marci@14
|
113 |
bfs_queue_type bfs_queue;
|
marci@9
|
114 |
bfs_queue.push(res_graph.first_out_edge(s));
|
marci@14
|
115 |
|
marci@14
|
116 |
typedef node_property_vector<aug_graph_type, bool> reached_type;
|
marci@14
|
117 |
reached_type reached(res_graph, false);
|
marci@9
|
118 |
reached.put(s, true);
|
marci@9
|
119 |
|
marci@14
|
120 |
bfs_iterator1< aug_graph_type, reached_type >
|
marci@14
|
121 |
res_bfs(res_graph, bfs_queue, reached);
|
marci@14
|
122 |
|
marci@19
|
123 |
typedef node_property_vector<aug_graph_type, aug_graph_type::edge_iterator> pred_type;
|
marci@14
|
124 |
pred_type pred(res_graph);
|
marci@19
|
125 |
aug_graph_type::edge_iterator a;
|
marci@17
|
126 |
a.make_invalid();
|
marci@17
|
127 |
pred.put(s, a);
|
marci@14
|
128 |
|
marci@14
|
129 |
typedef node_property_vector<aug_graph_type, int> free_type;
|
marci@14
|
130 |
free_type free(res_graph);
|
marci@14
|
131 |
|
marci@9
|
132 |
//searching for augmenting path
|
marci@19
|
133 |
while ( res_bfs.valid() ) {
|
marci@14
|
134 |
//std::cout<<"KULSO ciklus itt jar: "<<G.id(res_graph.tail(res_bfs))<<"->"<<G.id(res_graph.head(res_bfs))<<std::endl;
|
marci@19
|
135 |
if (res_bfs.newly_reached()) {
|
marci@19
|
136 |
aug_graph_type::edge_iterator e;
|
marci@14
|
137 |
e=res_bfs;
|
marci@14
|
138 |
node_iterator v=res_graph.tail(e);
|
marci@14
|
139 |
node_iterator w=res_graph.head(e);
|
marci@14
|
140 |
//std::cout<<G.id(v)<<"->"<<G.id(w)<<", "<<G.id(w)<<" is newly reached";
|
marci@14
|
141 |
pred.put(w, e);
|
marci@19
|
142 |
if (pred.get(v).valid()) {
|
marci@14
|
143 |
free.put(w, std::min(free.get(v), e.free()));
|
marci@14
|
144 |
//std::cout <<" nem elso csucs: ";
|
marci@14
|
145 |
//std::cout <<"szabad kap eddig: "<< free.get(w) << " ";
|
marci@14
|
146 |
} else {
|
marci@14
|
147 |
free.put(w, e.free());
|
marci@14
|
148 |
//std::cout <<" elso csucs: ";
|
marci@14
|
149 |
//std::cout <<"szabad kap eddig: "<< free.get(w) << " ";
|
marci@14
|
150 |
}
|
marci@14
|
151 |
//std::cout<<std::endl;
|
marci@14
|
152 |
}
|
marci@14
|
153 |
|
marci@9
|
154 |
if (res_graph.head(res_bfs)==t) break;
|
marci@9
|
155 |
++res_bfs;
|
marci@9
|
156 |
}
|
marci@9
|
157 |
if (reached.get(t)) {
|
marci@9
|
158 |
augment=true;
|
marci@9
|
159 |
node_iterator n=t;
|
marci@9
|
160 |
T augment_value=free.get(t);
|
marci@9
|
161 |
std::cout<<"augmentation: ";
|
marci@19
|
162 |
while (pred.get(n).valid()) {
|
marci@19
|
163 |
aug_graph_type::edge_iterator e=pred.get(n);
|
marci@9
|
164 |
e.augment(augment_value);
|
marci@9
|
165 |
std::cout<<"("<<res_graph.tail(e)<< "->"<<res_graph.head(e)<<") ";
|
marci@9
|
166 |
n=res_graph.tail(e);
|
marci@9
|
167 |
}
|
marci@9
|
168 |
std::cout<<std::endl;
|
marci@9
|
169 |
}
|
marci@9
|
170 |
|
marci@14
|
171 |
std::cout << "actual flow: "<< std::endl;
|
marci@19
|
172 |
for(typename graph_type::each_edge_iterator e=G.first_edge(); e.valid(); ++e) {
|
marci@9
|
173 |
std::cout<<"("<<G.tail(e)<< "-"<<flow.get(e)<<"->"<<G.head(e)<<") ";
|
marci@9
|
174 |
}
|
marci@9
|
175 |
std::cout<<std::endl;
|
marci@9
|
176 |
|
marci@9
|
177 |
} while (augment);
|
marci@9
|
178 |
}
|
marci@9
|
179 |
};
|
marci@9
|
180 |
|
marci@9
|
181 |
} // namespace marci
|
marci@9
|
182 |
|
marci@9
|
183 |
#endif //MARCI_MAX_FLOW_HH
|