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_graph_traits.hh>
|
marci@9
|
7 |
#include <marci_property_vector.hh>
|
marci@9
|
8 |
#include <marci_bfs.hh>
|
marci@9
|
9 |
|
marci@9
|
10 |
namespace marci {
|
marci@9
|
11 |
|
marci@9
|
12 |
template<typename graph_type, typename T>
|
marci@9
|
13 |
class res_graph_type {
|
marci@9
|
14 |
typedef typename graph_traits<graph_type>::node_iterator node_iterator;
|
marci@9
|
15 |
typedef typename graph_traits<graph_type>::edge_iterator edge_iterator;
|
marci@9
|
16 |
typedef typename graph_traits<graph_type>::each_node_iterator each_node_iterator;
|
marci@9
|
17 |
typedef typename graph_traits<graph_type>::sym_edge_iterator sym_edge_iterator;
|
marci@9
|
18 |
|
marci@9
|
19 |
graph_type& G;
|
marci@9
|
20 |
edge_property_vector<graph_type, T>& flow;
|
marci@9
|
21 |
edge_property_vector<graph_type, T>& capacity;
|
marci@9
|
22 |
public:
|
marci@9
|
23 |
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
|
24 |
|
marci@9
|
25 |
class res_edge_it {
|
marci@9
|
26 |
friend class res_graph_type<graph_type, T>;
|
marci@9
|
27 |
protected:
|
marci@9
|
28 |
res_graph_type<graph_type, T>* resG;
|
marci@9
|
29 |
sym_edge_iterator sym;
|
marci@9
|
30 |
public:
|
marci@9
|
31 |
res_edge_it() { }
|
marci@9
|
32 |
//bool is_free() {
|
marci@9
|
33 |
//if (resG->G.a_node(sym)==resG->G.tail(sym)) {
|
marci@9
|
34 |
// return (resG->flow.get(sym)<resG->capacity.get(sym));
|
marci@9
|
35 |
//} else {
|
marci@9
|
36 |
// return (resG->flow.get(sym)>0);
|
marci@9
|
37 |
//}
|
marci@9
|
38 |
//}
|
marci@9
|
39 |
T free() {
|
marci@9
|
40 |
if (resG->G.a_node(sym)==resG->G.tail(sym)) {
|
marci@9
|
41 |
return (resG->capacity.get(sym)-resG->flow.get(sym));
|
marci@9
|
42 |
} else {
|
marci@9
|
43 |
return (resG->flow.get(sym));
|
marci@9
|
44 |
}
|
marci@9
|
45 |
}
|
marci@9
|
46 |
bool is_valid() { return sym.is_valid(); }
|
marci@9
|
47 |
void augment(T a) {
|
marci@9
|
48 |
if (resG->G.a_node(sym)==resG->G.tail(sym)) {
|
marci@9
|
49 |
resG->flow.put(sym, resG->flow.get(sym)+a);
|
marci@9
|
50 |
} else {
|
marci@9
|
51 |
resG->flow.put(sym, resG->flow.get(sym)-a);
|
marci@9
|
52 |
}
|
marci@9
|
53 |
}
|
marci@9
|
54 |
};
|
marci@9
|
55 |
|
marci@9
|
56 |
class res_out_edge_it : public res_edge_it {
|
marci@9
|
57 |
public:
|
marci@9
|
58 |
res_out_edge_it() { }
|
marci@9
|
59 |
res_out_edge_it(res_graph_type<graph_type, T>& _resG, const node_iterator& v) {
|
marci@9
|
60 |
resG=&_resG;
|
marci@9
|
61 |
sym=resG->G.first_sym_edge(v);
|
marci@9
|
62 |
while( sym.is_valid() && !(free()>0) ) { ++sym; }
|
marci@9
|
63 |
}
|
marci@9
|
64 |
res_out_edge_it& operator++() {
|
marci@9
|
65 |
++sym;
|
marci@9
|
66 |
while( sym.is_valid() && !(free()>0) ) { ++sym; }
|
marci@9
|
67 |
return *this;
|
marci@9
|
68 |
}
|
marci@9
|
69 |
};
|
marci@9
|
70 |
|
marci@9
|
71 |
res_out_edge_it first_out_edge(const node_iterator& v) {
|
marci@9
|
72 |
return res_out_edge_it(*this, v);
|
marci@9
|
73 |
}
|
marci@9
|
74 |
|
marci@9
|
75 |
each_node_iterator first_node() {
|
marci@9
|
76 |
return G.first_node();
|
marci@9
|
77 |
}
|
marci@9
|
78 |
|
marci@9
|
79 |
node_iterator tail(const res_edge_it& e) { return G.a_node(e.sym); }
|
marci@9
|
80 |
node_iterator head(const res_edge_it& e) { return G.b_node(e.sym); }
|
marci@9
|
81 |
|
marci@9
|
82 |
int id(const node_iterator& v) { return G.id(v); }
|
marci@9
|
83 |
|
marci@9
|
84 |
node_iterator invalid_node() { return G.invalid_node(); }
|
marci@9
|
85 |
res_edge_it invalid_edge() { res_edge_it n; n.sym=G.invalid_sym_edge(); return n; }
|
marci@9
|
86 |
|
marci@9
|
87 |
};
|
marci@9
|
88 |
|
marci@9
|
89 |
template <typename graph_type, typename T>
|
marci@9
|
90 |
struct graph_traits< res_graph_type<graph_type, T> > {
|
marci@9
|
91 |
typedef typename graph_traits<graph_type>::node_iterator node_iterator;
|
marci@9
|
92 |
typedef typename res_graph_type<graph_type, T>::res_edge_it edge_iterator;
|
marci@9
|
93 |
typedef typename graph_traits<graph_type>::each_node_iterator each_node_iterator;
|
marci@9
|
94 |
typedef typename res_graph_type<graph_type, T>::res_out_edge_it out_edge_iterator;
|
marci@9
|
95 |
};
|
marci@9
|
96 |
|
marci@9
|
97 |
template <typename graph_type, typename pred_type, typename free_type>
|
marci@9
|
98 |
struct flow_visitor {
|
marci@9
|
99 |
typedef typename graph_traits<graph_type>::node_iterator node_iterator;
|
marci@9
|
100 |
typedef typename graph_traits<graph_type>::edge_iterator edge_iterator;
|
marci@9
|
101 |
typedef typename graph_traits<graph_type>::each_node_iterator each_node_iterator;
|
marci@9
|
102 |
typedef typename graph_traits<graph_type>::out_edge_iterator out_edge_iterator;
|
marci@9
|
103 |
graph_type& G;
|
marci@9
|
104 |
pred_type& pred;
|
marci@9
|
105 |
free_type& free;
|
marci@9
|
106 |
flow_visitor(graph_type& _G, pred_type& _pred, free_type& _free) : G(_G), pred(_pred), free(_free) { }
|
marci@9
|
107 |
void at_previously_reached(out_edge_iterator& e) {
|
marci@9
|
108 |
//node_iterator v=G.tail(e);
|
marci@9
|
109 |
//node_iterator w=G.head(e);
|
marci@9
|
110 |
//std::cout<<G.id(v)<<"->"<<G.id(w)<<", "<<G.id(w)<<" is already reached";
|
marci@9
|
111 |
//std::cout<<std::endl;
|
marci@9
|
112 |
}
|
marci@9
|
113 |
void at_newly_reached(out_edge_iterator& e) {
|
marci@9
|
114 |
node_iterator v=G.tail(e);
|
marci@9
|
115 |
node_iterator w=G.head(e);
|
marci@9
|
116 |
//std::cout<<G.id(v)<<"->"<<G.id(w)<<", "<<G.id(w)<<" is newly reached";
|
marci@9
|
117 |
pred.put(w, e);
|
marci@9
|
118 |
if (pred.get(v).is_valid()) {
|
marci@9
|
119 |
free.put(w, std::min(free.get(v), e.free()));
|
marci@9
|
120 |
//std::cout <<" nem elso csucs: ";
|
marci@9
|
121 |
//std::cout <<"szabad kap eddig: "<< free.get(w) << " ";
|
marci@9
|
122 |
} else {
|
marci@9
|
123 |
free.put(w, e.free());
|
marci@9
|
124 |
//std::cout <<" elso csucs: ";
|
marci@9
|
125 |
//std::cout <<"szabad kap eddig: "<< free.get(w) << " ";
|
marci@9
|
126 |
}
|
marci@9
|
127 |
//std::cout<<std::endl;
|
marci@9
|
128 |
}
|
marci@9
|
129 |
};
|
marci@9
|
130 |
|
marci@9
|
131 |
template <typename graph_type, typename T>
|
marci@9
|
132 |
struct max_flow_type {
|
marci@9
|
133 |
|
marci@9
|
134 |
typedef typename graph_traits<graph_type>::node_iterator node_iterator;
|
marci@9
|
135 |
typedef typename graph_traits<graph_type>::edge_iterator edge_iterator;
|
marci@9
|
136 |
typedef typename graph_traits<graph_type>::each_node_iterator each_node_iterator;
|
marci@9
|
137 |
typedef typename graph_traits<graph_type>::out_edge_iterator out_edge_iterator;
|
marci@9
|
138 |
typedef typename graph_traits<graph_type>::in_edge_iterator in_edge_iterator;
|
marci@9
|
139 |
|
marci@9
|
140 |
graph_type& G;
|
marci@9
|
141 |
node_iterator s;
|
marci@9
|
142 |
node_iterator t;
|
marci@9
|
143 |
edge_property_vector<graph_type, T> flow;
|
marci@9
|
144 |
edge_property_vector<graph_type, T>& capacity;
|
marci@9
|
145 |
|
marci@9
|
146 |
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@9
|
147 |
for(each_node_iterator i=G.first_node(); i.is_valid(); ++i)
|
marci@9
|
148 |
for(out_edge_iterator j=G.first_out_edge(i); j.is_valid(); ++j)
|
marci@9
|
149 |
flow.put(j, 0);
|
marci@9
|
150 |
}
|
marci@9
|
151 |
void run() {
|
marci@9
|
152 |
typedef res_graph_type<graph_type, T> aug_graph_type;
|
marci@9
|
153 |
aug_graph_type res_graph(G, flow, capacity);
|
marci@9
|
154 |
|
marci@9
|
155 |
typedef std::queue<graph_traits<aug_graph_type>::out_edge_iterator> bfs_queue_type;
|
marci@9
|
156 |
bfs_queue_type bfs_queue;
|
marci@9
|
157 |
//bfs_queue.push(res_graph.first_out_edge(s));
|
marci@9
|
158 |
|
marci@9
|
159 |
typedef node_property_vector<aug_graph_type, bool> reached_type;
|
marci@9
|
160 |
//reached_type reached(res_graph, false);
|
marci@9
|
161 |
reached_type reached(res_graph);
|
marci@9
|
162 |
//reached.put(s, true);
|
marci@9
|
163 |
|
marci@9
|
164 |
typedef node_property_vector<aug_graph_type, graph_traits<aug_graph_type>::edge_iterator> pred_type;
|
marci@9
|
165 |
pred_type pred(res_graph);
|
marci@9
|
166 |
pred.put(s, res_graph.invalid_edge());
|
marci@9
|
167 |
|
marci@9
|
168 |
typedef node_property_vector<aug_graph_type, int> free_type;
|
marci@9
|
169 |
free_type free(res_graph);
|
marci@9
|
170 |
|
marci@9
|
171 |
typedef flow_visitor<aug_graph_type, pred_type, free_type> visitor_type;
|
marci@9
|
172 |
visitor_type vis(res_graph, pred, free);
|
marci@9
|
173 |
|
marci@9
|
174 |
bfs_iterator< aug_graph_type, reached_type, visitor_type >
|
marci@9
|
175 |
res_bfs(res_graph, bfs_queue, reached, vis);
|
marci@9
|
176 |
|
marci@9
|
177 |
//for(graph_traits<aug_graph_type>::each_node_iterator i=res_graph.first_node(); i.is_valid(); ++i) {
|
marci@9
|
178 |
//for(graph_traits<aug_graph_type>::out_edge_iterator j=res_graph.first_out_edge(i); j.is_valid(); ++j) {
|
marci@9
|
179 |
// std::cout<<"("<<res_graph.tail(j)<< "->"<<res_graph.head(j)<<") ";
|
marci@9
|
180 |
//}
|
marci@9
|
181 |
//}
|
marci@9
|
182 |
//std::cout<<std::endl;
|
marci@9
|
183 |
|
marci@9
|
184 |
//char c;
|
marci@9
|
185 |
bool augment;
|
marci@9
|
186 |
do {
|
marci@9
|
187 |
augment=false;
|
marci@9
|
188 |
|
marci@9
|
189 |
while (!bfs_queue.empty()) { bfs_queue.pop(); }
|
marci@9
|
190 |
bfs_queue.push(res_graph.first_out_edge(s));
|
marci@9
|
191 |
|
marci@9
|
192 |
for(graph_traits<aug_graph_type>::each_node_iterator i=res_graph.first_node(); i.is_valid(); ++i) { reached.put(i, false); }
|
marci@9
|
193 |
reached.put(s, true);
|
marci@9
|
194 |
|
marci@9
|
195 |
//searching for augmenting path
|
marci@9
|
196 |
while ( /*std::cin>>c &&*/ res_bfs.is_valid() ) {
|
marci@9
|
197 |
res_bfs.process();
|
marci@9
|
198 |
//if (res_graph.head(graph_traits<aug_graph_type>::out_edge_iterator(res_bfs))==t) break;
|
marci@9
|
199 |
if (res_graph.head(res_bfs)==t) break;
|
marci@9
|
200 |
//res_bfs.next();
|
marci@9
|
201 |
++res_bfs;
|
marci@9
|
202 |
}
|
marci@9
|
203 |
//for (; std::cin>>c && !res_bfs.finished() && res_graph.head(res_bfs.current())!=t; res_bfs.next()) { res_bfs.process(); }
|
marci@9
|
204 |
if (reached.get(t)) {
|
marci@9
|
205 |
augment=true;
|
marci@9
|
206 |
node_iterator n=t;
|
marci@9
|
207 |
T augment_value=free.get(t);
|
marci@9
|
208 |
std::cout<<"augmentation: ";
|
marci@9
|
209 |
while (pred.get(n).is_valid()) {
|
marci@9
|
210 |
graph_traits<aug_graph_type>::edge_iterator e=pred.get(n);
|
marci@9
|
211 |
e.augment(augment_value);
|
marci@9
|
212 |
std::cout<<"("<<res_graph.tail(e)<< "->"<<res_graph.head(e)<<") ";
|
marci@9
|
213 |
n=res_graph.tail(e);
|
marci@9
|
214 |
}
|
marci@9
|
215 |
std::cout<<std::endl;
|
marci@9
|
216 |
}
|
marci@9
|
217 |
|
marci@9
|
218 |
std::cout << "max flow:"<< std::endl;
|
marci@9
|
219 |
for(graph_traits<graph_type>::each_edge_iterator e=G.first_edge(); e.is_valid(); ++e) {
|
marci@9
|
220 |
std::cout<<"("<<G.tail(e)<< "-"<<flow.get(e)<<"->"<<G.head(e)<<") ";
|
marci@9
|
221 |
}
|
marci@9
|
222 |
std::cout<<std::endl;
|
marci@9
|
223 |
|
marci@9
|
224 |
} while (augment);
|
marci@9
|
225 |
}
|
marci@9
|
226 |
};
|
marci@9
|
227 |
|
marci@9
|
228 |
} // namespace marci
|
marci@9
|
229 |
|
marci@9
|
230 |
#endif //MARCI_MAX_FLOW_HH
|