alpar@74
|
1 |
// -*- mode:c++ -*-
|
alpar@74
|
2 |
|
alpar@74
|
3 |
#ifndef EDMONDS_KARP_HH
|
alpar@74
|
4 |
#define EDMONDS_KARP_HH
|
alpar@74
|
5 |
|
alpar@74
|
6 |
#include <queue>
|
alpar@74
|
7 |
|
alpar@74
|
8 |
//#include <marci_property_vector.hh>
|
alpar@74
|
9 |
|
alpar@74
|
10 |
#include <algorithm>
|
alpar@74
|
11 |
|
alpar@74
|
12 |
//#include <bfs_iterator.hh>
|
alpar@74
|
13 |
|
alpar@921
|
14 |
namespace lemon {
|
alpar@74
|
15 |
template <typename Graph, typename FlowMap, typename CapacityMap>
|
alpar@987
|
16 |
typename FlowMap::Value maxFlow(Graph &G,
|
alpar@74
|
17 |
FlowMap &f,
|
alpar@74
|
18 |
CapacityMap &c,
|
marci@95
|
19 |
typename Graph::NodeIt s,
|
marci@95
|
20 |
typename Graph::NodeIt t)
|
alpar@74
|
21 |
{
|
alpar@93
|
22 |
typedef typename Graph::NodeIt NodeIt;
|
alpar@91
|
23 |
typedef typename Graph::EachNodeIt EachNodeIt;
|
alpar@74
|
24 |
typedef typename Graph::EdgeIt EdgeIt;
|
alpar@74
|
25 |
typedef typename Graph::EachEdgeIt EachEdgeIt;
|
alpar@74
|
26 |
typedef typename Graph::OutEdgeIt OutEdgeIt;
|
alpar@74
|
27 |
typedef typename Graph::InEdgeIt InEdgeIt;
|
alpar@987
|
28 |
typedef typename FlowMap::Value T;
|
alpar@74
|
29 |
|
alpar@74
|
30 |
T flow_val = 0;
|
alpar@74
|
31 |
T aug_val;
|
alpar@74
|
32 |
|
alpar@93
|
33 |
for(EachEdgeIt e(G);G.valid(e);G.goNext(e))
|
alpar@74
|
34 |
f.set(e,0);
|
alpar@74
|
35 |
|
alpar@93
|
36 |
std::queue<NodeIt> bfs_queue;
|
alpar@74
|
37 |
typename Graph::NodeMap<int> visited(G); //0: unvisited,
|
alpar@74
|
38 |
//1: reached by a forward edge
|
alpar@74
|
39 |
//2: reached by a backward edge
|
alpar@74
|
40 |
//3: it is node s
|
alpar@74
|
41 |
typename Graph::NodeMap<EdgeIt> tree(G);
|
alpar@74
|
42 |
|
alpar@94
|
43 |
NodeIt gn; //FIXME: it might be too global for some people...
|
alpar@74
|
44 |
|
alpar@74
|
45 |
augment:
|
alpar@74
|
46 |
|
alpar@93
|
47 |
for(EachNodeIt n(G);G.valid(n);G.goNext(n))
|
alpar@74
|
48 |
visited.set(n,0);
|
alpar@74
|
49 |
|
alpar@74
|
50 |
visited.set(s,3);
|
alpar@74
|
51 |
|
alpar@74
|
52 |
//There must be a better way to do this:
|
alpar@74
|
53 |
while(!bfs_queue.empty()) bfs_queue.pop();
|
alpar@74
|
54 |
|
alpar@74
|
55 |
bfs_queue.push(s);
|
alpar@74
|
56 |
|
alpar@74
|
57 |
while(!bfs_queue.empty() && !visited.get(t))
|
alpar@74
|
58 |
{
|
alpar@93
|
59 |
NodeIt n(bfs_queue.front());
|
alpar@93
|
60 |
bfs_queue.pop();
|
alpar@93
|
61 |
for(OutEdgeIt e(G,n);G.valid(e);G.goNext(e))
|
alpar@74
|
62 |
if(f.get(e)<c.get(e) && //FIXME: <
|
alpar@74
|
63 |
!visited.get(G.bNode(e)))
|
alpar@74
|
64 |
{
|
alpar@93
|
65 |
NodeIt nn(G.bNode(e)); //It improves nothing
|
alpar@93
|
66 |
tree.set(nn,e);
|
alpar@93
|
67 |
visited.set(nn,1);
|
alpar@93
|
68 |
bfs_queue.push(nn);
|
alpar@74
|
69 |
}
|
alpar@93
|
70 |
for(InEdgeIt e(G,n);G.valid(e);G.goNext(e))
|
alpar@74
|
71 |
if(f.get(e)>0 && //FIXME: >
|
alpar@74
|
72 |
!visited.get(G.bNode(e)))
|
alpar@74
|
73 |
{
|
alpar@93
|
74 |
NodeIt nn(G.bNode(e));
|
alpar@93
|
75 |
tree.set(nn,e);
|
alpar@93
|
76 |
visited.set(nn,2);
|
alpar@93
|
77 |
bfs_queue.push(nn);
|
alpar@74
|
78 |
}
|
alpar@74
|
79 |
}
|
alpar@74
|
80 |
|
alpar@74
|
81 |
if(!visited.get(t)) return flow_val;
|
alpar@74
|
82 |
|
alpar@74
|
83 |
// Augmenting value computation
|
alpar@80
|
84 |
aug_val = visited.get(t)==1 ?
|
alpar@74
|
85 |
c.get(tree.get(t))-f.get(tree.get(t)) : f.get(tree.get(t));
|
alpar@74
|
86 |
//FIXME: I would need 'G.opposite(e,n)'
|
alpar@986
|
87 |
gn = visited.get(t)==1 ? G.source(tree.get(t)) : G.target(tree.get(t));
|
alpar@80
|
88 |
while(gn!=s) if(visited.get(gn)==1)
|
alpar@74
|
89 |
{
|
alpar@93
|
90 |
//FIXME: nonstandard gcc extension!
|
alpar@74
|
91 |
aug_val <?= c.get(tree.get(gn))-f.get(tree.get(gn));
|
alpar@986
|
92 |
gn=G.source(tree.get(gn));
|
alpar@74
|
93 |
}
|
alpar@74
|
94 |
else {
|
alpar@93
|
95 |
//FIXME: nonstandard gcc extension!
|
alpar@74
|
96 |
aug_val <?= f.get(tree.get(gn));
|
alpar@986
|
97 |
gn=G.target(tree.get(gn));
|
alpar@74
|
98 |
}
|
alpar@74
|
99 |
|
alpar@74
|
100 |
// The augmentation itself
|
alpar@74
|
101 |
gn = t;
|
alpar@80
|
102 |
while(gn!=s) if(visited.get(gn)==1)
|
alpar@74
|
103 |
{
|
alpar@74
|
104 |
f.set(tree.get(gn),f.get(tree.get(gn))+aug_val);
|
alpar@986
|
105 |
gn=G.source(tree.get(gn));
|
alpar@74
|
106 |
}
|
alpar@74
|
107 |
else {
|
alpar@74
|
108 |
f.set(tree.get(gn),f.get(tree.get(gn))-aug_val);
|
alpar@986
|
109 |
gn=G.target(tree.get(gn));
|
alpar@74
|
110 |
}
|
alpar@74
|
111 |
|
alpar@74
|
112 |
flow_val+=aug_val;
|
alpar@74
|
113 |
|
alpar@74
|
114 |
goto augment; // Vivat goto forever!
|
alpar@74
|
115 |
}
|
alpar@74
|
116 |
|
alpar@921
|
117 |
} // namespace lemon
|
alpar@74
|
118 |
|
alpar@74
|
119 |
#endif //EDMONDS_KARP_HH
|