gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Cut iterators for GomoryHuTree + doc cleanup + bug fixes (#66)
0 2 0
default
2 files changed with 325 insertions and 61 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
1 1
/* -*- C++ -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library
4 4
 *
5 5
 * Copyright (C) 2003-2008
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#ifndef LEMON_GOMORY_HU_TREE_H
20 20
#define LEMON_GOMORY_HU_TREE_H
21 21

	
22 22
#include <limits>
23 23

	
24
#include <lemon/core.h>
24 25
#include <lemon/preflow.h>
25 26
#include <lemon/concept_check.h>
26 27
#include <lemon/concepts/maps.h>
27 28

	
28 29
/// \ingroup min_cut
29 30
/// \file 
30 31
/// \brief Gomory-Hu cut tree in graphs.
31 32

	
32 33
namespace lemon {
33 34

	
34 35
  /// \ingroup min_cut
35 36
  ///
36 37
  /// \brief Gomory-Hu cut tree algorithm
37 38
  ///
38
  /// The Gomory-Hu tree is a tree on the nodeset of the digraph, but it
39
  /// may contain arcs which are not in the original digraph. It helps
40
  /// to calculate the minimum cut between all pairs of nodes, because
41
  /// the minimum capacity arc on the tree path between two nodes has
42
  /// the same weight as the minimum cut in the digraph between these
43
  /// nodes. Moreover this arc separates the nodes to two parts which
44
  /// determine this minimum cut.
39
  /// The Gomory-Hu tree is a tree on the node set of the graph, but it
40
  /// may contain edges which are not in the original digraph. It has the
41
  /// property that the minimum capacity edge of the path between two nodes 
42
  /// in this tree has the same weight as the minimum cut in the digraph
43
  /// between these nodes. Moreover the components obtained by removing
44
  /// this edge from the tree determine the corresponding minimum cut.
45
  ///
46
  /// Therefore once this tree is computed, the minimum cut between any pair
47
  /// of nodes can easily be obtained.
45 48
  /// 
46
  /// The algorithm calculates \e n-1 distinict minimum cuts with
47
  /// preflow algorithm, therefore the algorithm has
49
  /// The algorithm calculates \e n-1 distinct minimum cuts (currently with
50
  /// the \ref Preflow algorithm), therefore the algorithm has
48 51
  /// \f$(O(n^3\sqrt{e})\f$ overall time complexity. It calculates a
49
  /// rooted Gomory-Hu tree, the structure of the tree and the weights
50
  /// can be obtained with \c predNode() and \c predValue()
51
  /// functions. The \c minCutValue() and \c minCutMap() calculates
52
  /// rooted Gomory-Hu tree, its structure and the weights can be obtained
53
  /// by \c predNode(), \c predValue() and \c rootDist().
54
  /// 
55
  /// The members \c minCutMap() and \c minCutValue() calculate
52 56
  /// the minimum cut and the minimum cut value between any two node
53
  /// in the digraph.
54
  template <typename _Graph, 
55
	    typename _Capacity = typename _Graph::template EdgeMap<int> >
57
  /// in the digraph. You can also list (iterate on) the nodes and the
58
  /// edges of the cuts using MinCutNodeIt and MinCutEdgeIt.
59
  ///
60
  /// \tparam GR The undirected graph data structure the algorithm will run on
61
  /// \tparam CAP type of the EdgeMap describing the Edge capacities.
62
  /// it is typename GR::template EdgeMap<int> by default.
63
  template <typename GR,
64
	    typename CAP = typename GR::template EdgeMap<int>
65
            >
56 66
  class GomoryHuTree {
57 67
  public:
58 68

	
59 69
    /// The graph type
60
    typedef _Graph Graph;
61
    /// The capacity on edges
62
    typedef _Capacity Capacity;
70
    typedef GR Graph;
71
    /// The type if the edge capacity map
72
    typedef CAP Capacity;
63 73
    /// The value type of capacities
64 74
    typedef typename Capacity::Value Value;
65 75
    
66 76
  private:
67 77

	
68 78
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
69 79

	
70 80
    const Graph& _graph;
71 81
    const Capacity& _capacity;
72 82

	
73 83
    Node _root;
74 84
    typename Graph::template NodeMap<Node>* _pred;
75 85
    typename Graph::template NodeMap<Value>* _weight;
76 86
    typename Graph::template NodeMap<int>* _order;
77 87

	
78 88
    void createStructures() {
79 89
      if (!_pred) {
80 90
	_pred = new typename Graph::template NodeMap<Node>(_graph);
81 91
      }
82 92
      if (!_weight) {
83 93
	_weight = new typename Graph::template NodeMap<Value>(_graph);
84 94
      }
85 95
      if (!_order) {
86 96
	_order = new typename Graph::template NodeMap<int>(_graph);
87 97
      }
88 98
    }
89 99

	
90 100
    void destroyStructures() {
91 101
      if (_pred) {
92 102
	delete _pred;
93 103
      }
94 104
      if (_weight) {
95 105
	delete _weight;
96 106
      }
97 107
      if (_order) {
98 108
	delete _order;
99 109
      }
100 110
    }
101 111
  
102 112
  public:
103 113

	
104 114
    /// \brief Constructor
105 115
    ///
106 116
    /// Constructor
107
    /// \param graph The graph type.
117
    /// \param graph The graph the algorithm will run on.
108 118
    /// \param capacity The capacity map.
109 119
    GomoryHuTree(const Graph& graph, const Capacity& capacity) 
110 120
      : _graph(graph), _capacity(capacity),
111 121
	_pred(0), _weight(0), _order(0) 
112 122
    {
113 123
      checkConcept<concepts::ReadMap<Edge, Value>, Capacity>();
114 124
    }
115 125

	
116 126

	
117 127
    /// \brief Destructor
118 128
    ///
119 129
    /// Destructor
120 130
    ~GomoryHuTree() {
121 131
      destroyStructures();
122 132
    }
123 133

	
124
    /// \brief Initializes the internal data structures.
125
    ///
126
    /// Initializes the internal data structures.
127
    ///
134
    // \brief Initialize the internal data structures.
135
    //
136
    // This function initializes the internal data structures.
137
    //
128 138
    void init() {
129 139
      createStructures();
130 140

	
131 141
      _root = NodeIt(_graph);
132 142
      for (NodeIt n(_graph); n != INVALID; ++n) {
133 143
	_pred->set(n, _root);
134 144
	_order->set(n, -1);
135 145
      }
136 146
      _pred->set(_root, INVALID);
137 147
      _weight->set(_root, std::numeric_limits<Value>::max()); 
138 148
    }
139 149

	
140 150

	
141
    /// \brief Starts the algorithm
142
    ///
143
    /// Starts the algorithm.
151
    // \brief Start the algorithm
152
    //
153
    // This function starts the algorithm.
154
    //
155
    // \pre \ref init() must be called before using this function.
156
    //
144 157
    void start() {
145 158
      Preflow<Graph, Capacity> fa(_graph, _capacity, _root, INVALID);
146 159

	
147 160
      for (NodeIt n(_graph); n != INVALID; ++n) {
148 161
	if (n == _root) continue;
149 162

	
150 163
	Node pn = (*_pred)[n];
151 164
	fa.source(n);
152 165
	fa.target(pn);
153 166

	
154 167
	fa.runMinCut();
155 168

	
156 169
	_weight->set(n, fa.flowValue());
157 170

	
158 171
	for (NodeIt nn(_graph); nn != INVALID; ++nn) {
159 172
	  if (nn != n && fa.minCut(nn) && (*_pred)[nn] == pn) {
160 173
	    _pred->set(nn, n);
161 174
	  }
162 175
	}
163 176
	if ((*_pred)[pn] != INVALID && fa.minCut((*_pred)[pn])) {
164 177
	  _pred->set(n, (*_pred)[pn]);
165 178
	  _pred->set(pn, n);
166 179
	  _weight->set(n, (*_weight)[pn]);
167 180
	  _weight->set(pn, fa.flowValue());	
168 181
	}
169 182
      }
170 183

	
171 184
      _order->set(_root, 0);
172 185
      int index = 1;
173 186

	
174 187
      for (NodeIt n(_graph); n != INVALID; ++n) {
175 188
	std::vector<Node> st;
176 189
	Node nn = n;
177 190
	while ((*_order)[nn] == -1) {
178 191
	  st.push_back(nn);
179 192
	  nn = (*_pred)[nn];
180 193
	}
181 194
	while (!st.empty()) {
182 195
	  _order->set(st.back(), index++);
183 196
	  st.pop_back();
184 197
	}
185 198
      }
186 199
    }
187 200

	
188
    /// \brief Runs the Gomory-Hu algorithm.  
201
    ///\name Execution Control
202
 
203
    ///@{
204

	
205
    /// \brief Run the Gomory-Hu algorithm.
189 206
    ///
190
    /// Runs the Gomory-Hu algorithm.
191
    /// \note gh.run() is just a shortcut of the following code.
192
    /// \code
193
    ///   ght.init();
194
    ///   ght.start();
195
    /// \endcode
207
    /// This function runs the Gomory-Hu algorithm.
196 208
    void run() {
197 209
      init();
198 210
      start();
199 211
    }
212
    
213
    /// @}
200 214

	
201
    /// \brief Returns the predecessor node in the Gomory-Hu tree.
215
    ///\name Query Functions
216
    ///The results of the algorithm can be obtained using these
217
    ///functions.\n
218
    ///The \ref run() "run()" should be called before using them.\n
219
    ///See also MinCutNodeIt and MinCutEdgeIt
220

	
221
    ///@{
222

	
223
    /// \brief Return the predecessor node in the Gomory-Hu tree.
202 224
    ///
203
    /// Returns the predecessor node in the Gomory-Hu tree. If the node is
225
    /// This function returns the predecessor node in the Gomory-Hu tree.
226
    /// If the node is
204 227
    /// the root of the Gomory-Hu tree, then it returns \c INVALID.
205 228
    Node predNode(const Node& node) {
206 229
      return (*_pred)[node];
207 230
    }
208 231

	
209
    /// \brief Returns the weight of the predecessor arc in the
232
    /// \brief Return the distance from the root node in the Gomory-Hu tree.
233
    ///
234
    /// This function returns the distance of \c node from the root node
235
    /// in the Gomory-Hu tree.
236
    int rootDist(const Node& node) {
237
      return (*_order)[node];
238
    }
239

	
240
    /// \brief Return the weight of the predecessor edge in the
210 241
    /// Gomory-Hu tree.
211 242
    ///
212
    /// Returns the weight of the predecessor arc in the Gomory-Hu
213
    /// tree.  If the node is the root of the Gomory-Hu tree, the
214
    /// result is undefined.
243
    /// This function returns the weight of the predecessor edge in the
244
    /// Gomory-Hu tree.  If the node is the root, the result is undefined.
215 245
    Value predValue(const Node& node) {
216 246
      return (*_weight)[node];
217 247
    }
218 248

	
219
    /// \brief Returns the minimum cut value between two nodes
249
    /// \brief Return the minimum cut value between two nodes
220 250
    ///
221
    /// Returns the minimum cut value between two nodes. The
251
    /// This function returns the minimum cut value between two nodes. The
222 252
    /// algorithm finds the nearest common ancestor in the Gomory-Hu
223 253
    /// tree and calculates the minimum weight arc on the paths to
224 254
    /// the ancestor.
225 255
    Value minCutValue(const Node& s, const Node& t) const {
226 256
      Node sn = s, tn = t;
227 257
      Value value = std::numeric_limits<Value>::max();
228 258
      
229 259
      while (sn != tn) {
230 260
	if ((*_order)[sn] < (*_order)[tn]) {
231
	  if ((*_weight)[tn] < value) value = (*_weight)[tn];
261
	  if ((*_weight)[tn] <= value) value = (*_weight)[tn];
232 262
	  tn = (*_pred)[tn];
233 263
	} else {
234
	  if ((*_weight)[sn] < value) value = (*_weight)[sn];
264
	  if ((*_weight)[sn] <= value) value = (*_weight)[sn];
235 265
	  sn = (*_pred)[sn];
236 266
	}
237 267
      }
238 268
      return value;
239 269
    }
240 270

	
241
    /// \brief Returns the minimum cut between two nodes
271
    /// \brief Return the minimum cut between two nodes
242 272
    ///
243
    /// Returns the minimum cut value between two nodes. The
244
    /// algorithm finds the nearest common ancestor in the Gomory-Hu
245
    /// tree and calculates the minimum weight arc on the paths to
246
    /// the ancestor. Then it sets all nodes to the cut determined by
247
    /// this arc. The \c cutMap should be \ref concepts::ReadWriteMap
273
    /// This function returns the minimum cut between the nodes \c s and \c t
274
    /// the \r cutMap parameter by setting the nodes in the component of
275
    /// \c \s to true and the other nodes to false.
276
    ///
277
    /// The \c cutMap should be \ref concepts::ReadWriteMap
248 278
    /// "ReadWriteMap".
279
    ///
280
    /// For higher level interfaces, see MinCutNodeIt and MinCutEdgeIt
249 281
    template <typename CutMap>
250
    Value minCutMap(const Node& s, const Node& t, CutMap& cutMap) const {
282
    Value minCutMap(const Node& s, ///< Base node
283
                    const Node& t,
284
                    ///< The node you want to separate from Node s.
285
                    CutMap& cutMap
286
                    ///< The cut will be return in this map.
287
                    /// It must be a \c bool \ref concepts::ReadWriteMap
288
                    /// "ReadWriteMap" on the graph nodes.
289
                    ) const {
251 290
      Node sn = s, tn = t;
252

	
291
      bool s_root=false;
253 292
      Node rn = INVALID;
254 293
      Value value = std::numeric_limits<Value>::max();
255 294
      
256 295
      while (sn != tn) {
257 296
	if ((*_order)[sn] < (*_order)[tn]) {
258
	  if ((*_weight)[tn] < value) {
297
	  if ((*_weight)[tn] <= value) {
259 298
	    rn = tn;
299
            s_root = false;
260 300
	    value = (*_weight)[tn];
261 301
	  }
262 302
	  tn = (*_pred)[tn];
263 303
	} else {
264
	  if ((*_weight)[sn] < value) {
304
	  if ((*_weight)[sn] <= value) {
265 305
	    rn = sn;
306
            s_root = true;
266 307
	    value = (*_weight)[sn];
267 308
	  }
268 309
	  sn = (*_pred)[sn];
269 310
	}
270 311
      }
271 312

	
272 313
      typename Graph::template NodeMap<bool> reached(_graph, false);
273 314
      reached.set(_root, true);
274
      cutMap.set(_root, false);
315
      cutMap.set(_root, !s_root);
275 316
      reached.set(rn, true);
276
      cutMap.set(rn, true);
317
      cutMap.set(rn, s_root);
277 318

	
319
      std::vector<Node> st;
278 320
      for (NodeIt n(_graph); n != INVALID; ++n) {
279
	std::vector<Node> st;
280
	Node nn = n;
321
	st.clear();
322
        Node nn = n;
281 323
	while (!reached[nn]) {
282 324
	  st.push_back(nn);
283 325
	  nn = (*_pred)[nn];
284 326
	}
285 327
	while (!st.empty()) {
286 328
	  cutMap.set(st.back(), cutMap[nn]);
287 329
	  st.pop_back();
288 330
	}
289 331
      }
290 332
      
291 333
      return value;
292 334
    }
293 335

	
336
    ///@}
337

	
338
    friend class MinCutNodeIt;
339

	
340
    /// Iterate on the nodes of a minimum cut
341
    
342
    /// This iterator class lists the nodes of a minimum cut found by
343
    /// GomoryHuTree. Before using it, you must allocate a GomoryHuTree class,
344
    /// and call its \ref GomoryHuTree::run() "run()" method.
345
    ///
346
    /// This example counts the nodes in the minimum cut separating \c s from
347
    /// \c t.
348
    /// \code
349
    /// GomoruHuTree<Graph> gom(g, capacities);
350
    /// gom.run();
351
    /// int sum=0;
352
    /// for(GomoruHuTree<Graph>::MinCutNodeIt n(gom,s,t);n!=INVALID;++n) ++sum;
353
    /// \endcode
354
    class MinCutNodeIt
355
    {
356
      bool _side;
357
      typename Graph::NodeIt _node_it;
358
      typename Graph::template NodeMap<bool> _cut;
359
    public:
360
      /// Constructor
361

	
362
      /// Constructor
363
      ///
364
      MinCutNodeIt(GomoryHuTree const &gomory,
365
                   ///< The GomoryHuTree class. You must call its
366
                   ///  run() method
367
                   ///  before initializing this iterator
368
                   const Node& s, ///< Base node
369
                   const Node& t,
370
                   ///< The node you want to separate from Node s.
371
                   bool side=true
372
                   ///< If it is \c true (default) then the iterator lists
373
                   ///  the nodes of the component containing \c s,
374
                   ///  otherwise it lists the other component.
375
                   /// \note As the minimum cut is not always unique,
376
                   /// \code
377
                   /// MinCutNodeIt(gomory, s, t, true);
378
                   /// \endcode
379
                   /// and
380
                   /// \code
381
                   /// MinCutNodeIt(gomory, t, s, false);
382
                   /// \endcode
383
                   /// does not necessarily give the same set of nodes.
384
                   /// However it is ensured that
385
                   /// \code
386
                   /// MinCutNodeIt(gomory, s, t, true);
387
                   /// \endcode
388
                   /// and
389
                   /// \code
390
                   /// MinCutNodeIt(gomory, s, t, false);
391
                   /// \endcode
392
                   /// together list each node exactly once.
393
                   )
394
        : _side(side), _cut(gomory._graph)
395
      {
396
        gomory.minCutMap(s,t,_cut);
397
        for(_node_it=typename Graph::NodeIt(gomory._graph);
398
            _node_it!=INVALID && _cut[_node_it]!=_side;
399
            ++_node_it) {}
400
      }
401
      /// Conversion to Node
402

	
403
      /// Conversion to Node
404
      ///
405
      operator typename Graph::Node() const
406
      {
407
        return _node_it;
408
      }
409
      bool operator==(Invalid) { return _node_it==INVALID; }
410
      bool operator!=(Invalid) { return _node_it!=INVALID; }
411
      /// Next node
412

	
413
      /// Next node
414
      ///
415
      MinCutNodeIt &operator++()
416
      {
417
        for(++_node_it;_node_it!=INVALID&&_cut[_node_it]!=_side;++_node_it) {}
418
        return *this;
419
      }
420
      /// Postfix incrementation
421

	
422
      /// Postfix incrementation
423
      ///
424
      /// \warning This incrementation
425
      /// returns a \c Node, not a \ref MinCutNodeIt, as one may
426
      /// expect.
427
      typename Graph::Node operator++(int)
428
      {
429
        typename Graph::Node n=*this;
430
        ++(*this);
431
        return n;
432
      }
433
    };
434
    
435
    friend class MinCutEdgeIt;
436
    
437
    /// Iterate on the edges of a minimum cut
438
    
439
    /// This iterator class lists the edges of a minimum cut found by
440
    /// GomoryHuTree. Before using it, you must allocate a GomoryHuTree class,
441
    /// and call its \ref GomoryHuTree::run() "run()" method.
442
    ///
443
    /// This example computes the value of the minimum cut separating \c s from
444
    /// \c t.
445
    /// \code
446
    /// GomoruHuTree<Graph> gom(g, capacities);
447
    /// gom.run();
448
    /// int value=0;
449
    /// for(GomoruHuTree<Graph>::MinCutEdgeIt e(gom,s,t);e!=INVALID;++e)
450
    ///   value+=capacities[e];
451
    /// \endcode
452
    /// the result will be the same as it is returned by
453
    /// \ref GomoryHuTree::minCostValue() "gom.minCostValue(s,t)"
454
    class MinCutEdgeIt
455
    {
456
      bool _side;
457
      const Graph &_graph;
458
      typename Graph::NodeIt _node_it;
459
      typename Graph::OutArcIt _arc_it;
460
      typename Graph::template NodeMap<bool> _cut;
461
      void step()
462
      {
463
        ++_arc_it;
464
        while(_node_it!=INVALID && _arc_it==INVALID)
465
          {
466
            for(++_node_it;_node_it!=INVALID&&!_cut[_node_it];++_node_it) {}
467
            if(_node_it!=INVALID)
468
              _arc_it=typename Graph::OutArcIt(_graph,_node_it);
469
          }
470
      }
471
      
472
    public:
473
      MinCutEdgeIt(GomoryHuTree const &gomory,
474
                   ///< The GomoryHuTree class. You must call its
475
                   ///  run() method
476
                   ///  before initializing this iterator
477
                   const Node& s,  ///< Base node
478
                   const Node& t,
479
                   ///< The node you want to separate from Node s.
480
                   bool side=true
481
                   ///< If it is \c true (default) then the listed arcs
482
                   ///  will be oriented from the
483
                   ///  the nodes of the component containing \c s,
484
                   ///  otherwise they will be oriented in the opposite
485
                   ///  direction.
486
                   )
487
        : _graph(gomory._graph), _cut(_graph)
488
      {
489
        gomory.minCutMap(s,t,_cut);
490
        if(!side)
491
          for(typename Graph::NodeIt n(_graph);n!=INVALID;++n)
492
            _cut[n]=!_cut[n];
493

	
494
        for(_node_it=typename Graph::NodeIt(_graph);
495
            _node_it!=INVALID && !_cut[_node_it];
496
            ++_node_it) {}
497
        _arc_it = _node_it!=INVALID ?
498
          typename Graph::OutArcIt(_graph,_node_it) : INVALID;
499
        while(_node_it!=INVALID && _arc_it == INVALID)
500
          {
501
            for(++_node_it; _node_it!=INVALID&&!_cut[_node_it]; ++_node_it) {}
502
            if(_node_it!=INVALID)
503
              _arc_it= typename Graph::OutArcIt(_graph,_node_it);
504
          }
505
        while(_arc_it!=INVALID && _cut[_graph.target(_arc_it)]) step();
506
      }
507
      /// Conversion to Arc
508

	
509
      /// Conversion to Arc
510
      ///
511
      operator typename Graph::Arc() const
512
      {
513
        return _arc_it;
514
      }
515
      /// Conversion to Edge
516

	
517
      /// Conversion to Edge
518
      ///
519
      operator typename Graph::Edge() const
520
      {
521
        return _arc_it;
522
      }
523
      bool operator==(Invalid) { return _node_it==INVALID; }
524
      bool operator!=(Invalid) { return _node_it!=INVALID; }
525
      /// Next edge
526

	
527
      /// Next edge
528
      ///
529
      MinCutEdgeIt &operator++()
530
      {
531
        step();
532
        while(_arc_it!=INVALID && _cut[_graph.target(_arc_it)]) step();
533
        return *this;
534
      }
535
      /// Postfix incrementation
536
      
537
      /// Postfix incrementation
538
      ///
539
      /// \warning This incrementation
540
      /// returns a \c Arc, not a \ref MinCutEdgeIt, as one may
541
      /// expect.
542
      typename Graph::Arc operator++(int)
543
      {
544
        typename Graph::Arc e=*this;
545
        ++(*this);
546
        return e;
547
      }
548
    };
549

	
294 550
  };
295 551

	
296 552
}
297 553

	
298 554
#endif
Ignore white space 786432 line context
1 1
#include <iostream>
2 2

	
3 3
#include "test_tools.h"
4 4
#include <lemon/smart_graph.h>
5
#include <lemon/adaptors.h>
6 5
#include <lemon/lgf_reader.h>
7
#include <lemon/lgf_writer.h>
8
#include <lemon/dimacs.h>
9
#include <lemon/time_measure.h>
10 6
#include <lemon/gomory_hu_tree.h>
11 7
#include <cstdlib>
12 8

	
13 9
using namespace std;
14 10
using namespace lemon;
15 11

	
16 12
typedef SmartGraph Graph;
17 13

	
18 14
char test_lgf[] =
19 15
  "@nodes\n"
20 16
  "label\n"
21 17
  "0\n"
22 18
  "1\n"
23 19
  "2\n"
24 20
  "3\n"
25 21
  "4\n"
26 22
  "@arcs\n"
27 23
  "     label capacity\n"
28 24
  "0 1  0     1\n"
29 25
  "1 2  1     1\n"
30 26
  "2 3  2     1\n"
31 27
  "0 3  4     5\n"
32 28
  "0 3  5     10\n"
33 29
  "0 3  6     7\n"
34 30
  "4 2  7     1\n"
35 31
  "@attributes\n"
36 32
  "source 0\n"
37 33
  "target 3\n";
38 34
  
39 35
GRAPH_TYPEDEFS(Graph);
40 36
typedef Graph::EdgeMap<int> IntEdgeMap;
41 37
typedef Graph::NodeMap<bool> BoolNodeMap;
42 38

	
43 39
int cutValue(const Graph& graph, const BoolNodeMap& cut,
44 40
	     const IntEdgeMap& capacity) {
45 41

	
46 42
  int sum = 0;
47 43
  for (EdgeIt e(graph); e != INVALID; ++e) {
48 44
    Node s = graph.u(e);
49 45
    Node t = graph.v(e);
50 46

	
51 47
    if (cut[s] != cut[t]) {
52 48
      sum += capacity[e];
53 49
    }
54 50
  }
55 51
  return sum;
56 52
}
57 53

	
58 54

	
59 55
int main() {
60 56
  Graph graph;
61 57
  IntEdgeMap capacity(graph);
62 58

	
63 59
  std::istringstream input(test_lgf);
64 60
  GraphReader<Graph>(graph, input).
65 61
    edgeMap("capacity", capacity).run();
66 62

	
67 63
  GomoryHuTree<Graph> ght(graph, capacity);
68 64
  ght.init();
69 65
  ght.run();
70 66

	
71 67
  for (NodeIt u(graph); u != INVALID; ++u) {
72 68
    for (NodeIt v(graph); v != u; ++v) {
73 69
      Preflow<Graph, IntEdgeMap> pf(graph, capacity, u, v);
74 70
      pf.runMinCut();
75 71
      BoolNodeMap cm(graph);
76 72
      ght.minCutMap(u, v, cm);
77 73
      check(pf.flowValue() == ght.minCutValue(u, v), "Wrong cut 1");
78 74
      check(cm[u] != cm[v], "Wrong cut 3");
79 75
      check(pf.flowValue() == cutValue(graph, cm, capacity), "Wrong cut 2");
76

	
77
      int sum=0;
78
      for(GomoryHuTree<Graph>::MinCutEdgeIt a(ght, u, v);a!=INVALID;++a)
79
        sum+=capacity[a]; 
80
      check(sum == ght.minCutValue(u, v), "Problem with MinCutEdgeIt");
81

	
82
      sum=0;
83
      for(GomoryHuTree<Graph>::MinCutNodeIt n(ght, u, v,true);n!=INVALID;++n)
84
        sum++;
85
      for(GomoryHuTree<Graph>::MinCutNodeIt n(ght, u, v,false);n!=INVALID;++n)
86
        sum++;
87
      check(sum == countNodes(graph), "Problem with MinCutNodeIt");
80 88
      
81 89
    }
82 90
  }
83 91
  
84 92
  return 0;
85 93
}
0 comments (0 inline)