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

	
19
#ifndef LEMON_MAX_MATCHING_H
20
#define LEMON_MAX_MATCHING_H
21

	
22
#include <vector>
23
#include <queue>
24
#include <set>
25
#include <limits>
26

	
27
#include <lemon/core.h>
28
#include <lemon/unionfind.h>
29
#include <lemon/bin_heap.h>
30
#include <lemon/maps.h>
31

	
32
///\ingroup matching
33
///\file
34
///\brief Maximum matching algorithms in general graphs.
35

	
36
namespace lemon {
37

	
38
  /// \ingroup matching
39
  ///
40
  /// \brief Maximum cardinality matching in general graphs
41
  ///
42
  /// This class implements Edmonds' alternating forest matching algorithm
43
  /// for finding a maximum cardinality matching in a general undirected graph.
44
  /// It can be started from an arbitrary initial matching 
45
  /// (the default is the empty one).
46
  ///
47
  /// The dual solution of the problem is a map of the nodes to
48
  /// \ref MaxMatching::Status "Status", having values \c EVEN (or \c D),
49
  /// \c ODD (or \c A) and \c MATCHED (or \c C) defining the Gallai-Edmonds
50
  /// decomposition of the graph. The nodes in \c EVEN/D induce a subgraph
51
  /// with factor-critical components, the nodes in \c ODD/A form the
52
  /// canonical barrier, and the nodes in \c MATCHED/C induce a graph having
53
  /// a perfect matching. The number of the factor-critical components
54
  /// minus the number of barrier nodes is a lower bound on the
55
  /// unmatched nodes, and the matching is optimal if and only if this bound is
56
  /// tight. This decomposition can be obtained using \ref status() or
57
  /// \ref statusMap() after running the algorithm.
58
  ///
59
  /// \tparam GR The undirected graph type the algorithm runs on.
60
  template <typename GR>
61
  class MaxMatching {
62
  public:
63

	
64
    /// The graph type of the algorithm
65
    typedef GR Graph;
66
    /// The type of the matching map
67
    typedef typename Graph::template NodeMap<typename Graph::Arc>
68
    MatchingMap;
69

	
70
    ///\brief Status constants for Gallai-Edmonds decomposition.
71
    ///
72
    ///These constants are used for indicating the Gallai-Edmonds 
73
    ///decomposition of a graph. The nodes with status \c EVEN (or \c D)
74
    ///induce a subgraph with factor-critical components, the nodes with
75
    ///status \c ODD (or \c A) form the canonical barrier, and the nodes
76
    ///with status \c MATCHED (or \c C) induce a subgraph having a 
77
    ///perfect matching.
78
    enum Status {
79
      EVEN = 1,       ///< = 1. (\c D is an alias for \c EVEN.)
80
      D = 1,
81
      MATCHED = 0,    ///< = 0. (\c C is an alias for \c MATCHED.)
82
      C = 0,
83
      ODD = -1,       ///< = -1. (\c A is an alias for \c ODD.)
84
      A = -1,
85
      UNMATCHED = -2  ///< = -2.
86
    };
87

	
88
    /// The type of the status map
89
    typedef typename Graph::template NodeMap<Status> StatusMap;
90

	
91
  private:
92

	
93
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
94

	
95
    typedef UnionFindEnum<IntNodeMap> BlossomSet;
96
    typedef ExtendFindEnum<IntNodeMap> TreeSet;
97
    typedef RangeMap<Node> NodeIntMap;
98
    typedef MatchingMap EarMap;
99
    typedef std::vector<Node> NodeQueue;
100

	
101
    const Graph& _graph;
102
    MatchingMap* _matching;
103
    StatusMap* _status;
104

	
105
    EarMap* _ear;
106

	
107
    IntNodeMap* _blossom_set_index;
108
    BlossomSet* _blossom_set;
109
    NodeIntMap* _blossom_rep;
110

	
111
    IntNodeMap* _tree_set_index;
112
    TreeSet* _tree_set;
113

	
114
    NodeQueue _node_queue;
115
    int _process, _postpone, _last;
116

	
117
    int _node_num;
118

	
119
  private:
120

	
121
    void createStructures() {
122
      _node_num = countNodes(_graph);
123
      if (!_matching) {
124
        _matching = new MatchingMap(_graph);
125
      }
126
      if (!_status) {
127
        _status = new StatusMap(_graph);
128
      }
129
      if (!_ear) {
130
        _ear = new EarMap(_graph);
131
      }
132
      if (!_blossom_set) {
133
        _blossom_set_index = new IntNodeMap(_graph);
134
        _blossom_set = new BlossomSet(*_blossom_set_index);
135
      }
136
      if (!_blossom_rep) {
137
        _blossom_rep = new NodeIntMap(_node_num);
138
      }
139
      if (!_tree_set) {
140
        _tree_set_index = new IntNodeMap(_graph);
141
        _tree_set = new TreeSet(*_tree_set_index);
142
      }
143
      _node_queue.resize(_node_num);
144
    }
145

	
146
    void destroyStructures() {
147
      if (_matching) {
148
        delete _matching;
149
      }
150
      if (_status) {
151
        delete _status;
152
      }
153
      if (_ear) {
154
        delete _ear;
155
      }
156
      if (_blossom_set) {
157
        delete _blossom_set;
158
        delete _blossom_set_index;
159
      }
160
      if (_blossom_rep) {
161
        delete _blossom_rep;
162
      }
163
      if (_tree_set) {
164
        delete _tree_set_index;
165
        delete _tree_set;
166
      }
167
    }
168

	
169
    void processDense(const Node& n) {
170
      _process = _postpone = _last = 0;
171
      _node_queue[_last++] = n;
172

	
173
      while (_process != _last) {
174
        Node u = _node_queue[_process++];
175
        for (OutArcIt a(_graph, u); a != INVALID; ++a) {
176
          Node v = _graph.target(a);
177
          if ((*_status)[v] == MATCHED) {
178
            extendOnArc(a);
179
          } else if ((*_status)[v] == UNMATCHED) {
180
            augmentOnArc(a);
181
            return;
182
          }
183
        }
184
      }
185

	
186
      while (_postpone != _last) {
187
        Node u = _node_queue[_postpone++];
188

	
189
        for (OutArcIt a(_graph, u); a != INVALID ; ++a) {
190
          Node v = _graph.target(a);
191

	
192
          if ((*_status)[v] == EVEN) {
193
            if (_blossom_set->find(u) != _blossom_set->find(v)) {
194
              shrinkOnEdge(a);
195
            }
196
          }
197

	
198
          while (_process != _last) {
199
            Node w = _node_queue[_process++];
200
            for (OutArcIt b(_graph, w); b != INVALID; ++b) {
201
              Node x = _graph.target(b);
202
              if ((*_status)[x] == MATCHED) {
203
                extendOnArc(b);
204
              } else if ((*_status)[x] == UNMATCHED) {
205
                augmentOnArc(b);
206
                return;
207
              }
208
            }
209
          }
210
        }
211
      }
212
    }
213

	
214
    void processSparse(const Node& n) {
215
      _process = _last = 0;
216
      _node_queue[_last++] = n;
217
      while (_process != _last) {
218
        Node u = _node_queue[_process++];
219
        for (OutArcIt a(_graph, u); a != INVALID; ++a) {
220
          Node v = _graph.target(a);
221

	
222
          if ((*_status)[v] == EVEN) {
223
            if (_blossom_set->find(u) != _blossom_set->find(v)) {
224
              shrinkOnEdge(a);
225
            }
226
          } else if ((*_status)[v] == MATCHED) {
227
            extendOnArc(a);
228
          } else if ((*_status)[v] == UNMATCHED) {
229
            augmentOnArc(a);
230
            return;
231
          }
232
        }
233
      }
234
    }
235

	
236
    void shrinkOnEdge(const Edge& e) {
237
      Node nca = INVALID;
238

	
239
      {
240
        std::set<Node> left_set, right_set;
241

	
242
        Node left = (*_blossom_rep)[_blossom_set->find(_graph.u(e))];
243
        left_set.insert(left);
244

	
245
        Node right = (*_blossom_rep)[_blossom_set->find(_graph.v(e))];
246
        right_set.insert(right);
247

	
248
        while (true) {
249
          if ((*_matching)[left] == INVALID) break;
250
          left = _graph.target((*_matching)[left]);
251
          left = (*_blossom_rep)[_blossom_set->
252
                                 find(_graph.target((*_ear)[left]))];
253
          if (right_set.find(left) != right_set.end()) {
254
            nca = left;
255
            break;
256
          }
257
          left_set.insert(left);
258

	
259
          if ((*_matching)[right] == INVALID) break;
260
          right = _graph.target((*_matching)[right]);
261
          right = (*_blossom_rep)[_blossom_set->
262
                                  find(_graph.target((*_ear)[right]))];
263
          if (left_set.find(right) != left_set.end()) {
264
            nca = right;
265
            break;
266
          }
267
          right_set.insert(right);
268
        }
269

	
270
        if (nca == INVALID) {
271
          if ((*_matching)[left] == INVALID) {
272
            nca = right;
273
            while (left_set.find(nca) == left_set.end()) {
274
              nca = _graph.target((*_matching)[nca]);
275
              nca =(*_blossom_rep)[_blossom_set->
276
                                   find(_graph.target((*_ear)[nca]))];
277
            }
278
          } else {
279
            nca = left;
280
            while (right_set.find(nca) == right_set.end()) {
281
              nca = _graph.target((*_matching)[nca]);
282
              nca = (*_blossom_rep)[_blossom_set->
283
                                   find(_graph.target((*_ear)[nca]))];
284
            }
285
          }
286
        }
287
      }
288

	
289
      {
290

	
291
        Node node = _graph.u(e);
292
        Arc arc = _graph.direct(e, true);
293
        Node base = (*_blossom_rep)[_blossom_set->find(node)];
294

	
295
        while (base != nca) {
296
          (*_ear)[node] = arc;
297

	
298
          Node n = node;
299
          while (n != base) {
300
            n = _graph.target((*_matching)[n]);
301
            Arc a = (*_ear)[n];
302
            n = _graph.target(a);
303
            (*_ear)[n] = _graph.oppositeArc(a);
304
          }
305
          node = _graph.target((*_matching)[base]);
306
          _tree_set->erase(base);
307
          _tree_set->erase(node);
308
          _blossom_set->insert(node, _blossom_set->find(base));
309
          (*_status)[node] = EVEN;
310
          _node_queue[_last++] = node;
311
          arc = _graph.oppositeArc((*_ear)[node]);
312
          node = _graph.target((*_ear)[node]);
313
          base = (*_blossom_rep)[_blossom_set->find(node)];
314
          _blossom_set->join(_graph.target(arc), base);
315
        }
316
      }
317

	
318
      (*_blossom_rep)[_blossom_set->find(nca)] = nca;
319

	
320
      {
321

	
322
        Node node = _graph.v(e);
323
        Arc arc = _graph.direct(e, false);
324
        Node base = (*_blossom_rep)[_blossom_set->find(node)];
325

	
326
        while (base != nca) {
327
          (*_ear)[node] = arc;
328

	
329
          Node n = node;
330
          while (n != base) {
331
            n = _graph.target((*_matching)[n]);
332
            Arc a = (*_ear)[n];
333
            n = _graph.target(a);
334
            (*_ear)[n] = _graph.oppositeArc(a);
335
          }
336
          node = _graph.target((*_matching)[base]);
337
          _tree_set->erase(base);
338
          _tree_set->erase(node);
339
          _blossom_set->insert(node, _blossom_set->find(base));
340
          (*_status)[node] = EVEN;
341
          _node_queue[_last++] = node;
342
          arc = _graph.oppositeArc((*_ear)[node]);
343
          node = _graph.target((*_ear)[node]);
344
          base = (*_blossom_rep)[_blossom_set->find(node)];
345
          _blossom_set->join(_graph.target(arc), base);
346
        }
347
      }
348

	
349
      (*_blossom_rep)[_blossom_set->find(nca)] = nca;
350
    }
351

	
352
    void extendOnArc(const Arc& a) {
353
      Node base = _graph.source(a);
354
      Node odd = _graph.target(a);
355

	
356
      (*_ear)[odd] = _graph.oppositeArc(a);
357
      Node even = _graph.target((*_matching)[odd]);
358
      (*_blossom_rep)[_blossom_set->insert(even)] = even;
359
      (*_status)[odd] = ODD;
360
      (*_status)[even] = EVEN;
361
      int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(base)]);
362
      _tree_set->insert(odd, tree);
363
      _tree_set->insert(even, tree);
364
      _node_queue[_last++] = even;
365

	
366
    }
367

	
368
    void augmentOnArc(const Arc& a) {
369
      Node even = _graph.source(a);
370
      Node odd = _graph.target(a);
371

	
372
      int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(even)]);
373

	
374
      (*_matching)[odd] = _graph.oppositeArc(a);
375
      (*_status)[odd] = MATCHED;
376

	
377
      Arc arc = (*_matching)[even];
378
      (*_matching)[even] = a;
379

	
380
      while (arc != INVALID) {
381
        odd = _graph.target(arc);
382
        arc = (*_ear)[odd];
383
        even = _graph.target(arc);
384
        (*_matching)[odd] = arc;
385
        arc = (*_matching)[even];
386
        (*_matching)[even] = _graph.oppositeArc((*_matching)[odd]);
387
      }
388

	
389
      for (typename TreeSet::ItemIt it(*_tree_set, tree);
390
           it != INVALID; ++it) {
391
        if ((*_status)[it] == ODD) {
392
          (*_status)[it] = MATCHED;
393
        } else {
394
          int blossom = _blossom_set->find(it);
395
          for (typename BlossomSet::ItemIt jt(*_blossom_set, blossom);
396
               jt != INVALID; ++jt) {
397
            (*_status)[jt] = MATCHED;
398
          }
399
          _blossom_set->eraseClass(blossom);
400
        }
401
      }
402
      _tree_set->eraseClass(tree);
403

	
404
    }
405

	
406
  public:
407

	
408
    /// \brief Constructor
409
    ///
410
    /// Constructor.
411
    MaxMatching(const Graph& graph)
412
      : _graph(graph), _matching(0), _status(0), _ear(0),
413
        _blossom_set_index(0), _blossom_set(0), _blossom_rep(0),
414
        _tree_set_index(0), _tree_set(0) {}
415

	
416
    ~MaxMatching() {
417
      destroyStructures();
418
    }
419

	
420
    /// \name Execution Control
421
    /// The simplest way to execute the algorithm is to use the
422
    /// \c run() member function.\n
423
    /// If you need better control on the execution, you have to call
424
    /// one of the functions \ref init(), \ref greedyInit() or
425
    /// \ref matchingInit() first, then you can start the algorithm with
426
    /// \ref startSparse() or \ref startDense().
427

	
428
    ///@{
429

	
430
    /// \brief Set the initial matching to the empty matching.
431
    ///
432
    /// This function sets the initial matching to the empty matching.
433
    void init() {
434
      createStructures();
435
      for(NodeIt n(_graph); n != INVALID; ++n) {
436
        (*_matching)[n] = INVALID;
437
        (*_status)[n] = UNMATCHED;
438
      }
439
    }
440

	
441
    /// \brief Find an initial matching in a greedy way.
442
    ///
443
    /// This function finds an initial matching in a greedy way.
444
    void greedyInit() {
445
      createStructures();
446
      for (NodeIt n(_graph); n != INVALID; ++n) {
447
        (*_matching)[n] = INVALID;
448
        (*_status)[n] = UNMATCHED;
449
      }
450
      for (NodeIt n(_graph); n != INVALID; ++n) {
451
        if ((*_matching)[n] == INVALID) {
452
          for (OutArcIt a(_graph, n); a != INVALID ; ++a) {
453
            Node v = _graph.target(a);
454
            if ((*_matching)[v] == INVALID && v != n) {
455
              (*_matching)[n] = a;
456
              (*_status)[n] = MATCHED;
457
              (*_matching)[v] = _graph.oppositeArc(a);
458
              (*_status)[v] = MATCHED;
459
              break;
460
            }
461
          }
462
        }
463
      }
464
    }
465

	
466

	
467
    /// \brief Initialize the matching from a map.
468
    ///
469
    /// This function initializes the matching from a \c bool valued edge
470
    /// map. This map should have the property that there are no two incident
471
    /// edges with \c true value, i.e. it really contains a matching.
472
    /// \return \c true if the map contains a matching.
473
    template <typename MatchingMap>
474
    bool matchingInit(const MatchingMap& matching) {
475
      createStructures();
476

	
477
      for (NodeIt n(_graph); n != INVALID; ++n) {
478
        (*_matching)[n] = INVALID;
479
        (*_status)[n] = UNMATCHED;
480
      }
481
      for(EdgeIt e(_graph); e!=INVALID; ++e) {
482
        if (matching[e]) {
483

	
484
          Node u = _graph.u(e);
485
          if ((*_matching)[u] != INVALID) return false;
486
          (*_matching)[u] = _graph.direct(e, true);
487
          (*_status)[u] = MATCHED;
488

	
489
          Node v = _graph.v(e);
490
          if ((*_matching)[v] != INVALID) return false;
491
          (*_matching)[v] = _graph.direct(e, false);
492
          (*_status)[v] = MATCHED;
493
        }
494
      }
495
      return true;
496
    }
497

	
498
    /// \brief Start Edmonds' algorithm
499
    ///
500
    /// This function runs the original Edmonds' algorithm.
501
    ///
502
    /// \pre \ref Init(), \ref greedyInit() or \ref matchingInit() must be
503
    /// called before using this function.
504
    void startSparse() {
505
      for(NodeIt n(_graph); n != INVALID; ++n) {
506
        if ((*_status)[n] == UNMATCHED) {
507
          (*_blossom_rep)[_blossom_set->insert(n)] = n;
508
          _tree_set->insert(n);
509
          (*_status)[n] = EVEN;
510
          processSparse(n);
511
        }
512
      }
513
    }
514

	
515
    /// \brief Start Edmonds' algorithm with a heuristic improvement 
516
    /// for dense graphs
517
    ///
518
    /// This function runs Edmonds' algorithm with a heuristic of postponing
519
    /// shrinks, therefore resulting in a faster algorithm for dense graphs.
520
    ///
521
    /// \pre \ref Init(), \ref greedyInit() or \ref matchingInit() must be
522
    /// called before using this function.
523
    void startDense() {
524
      for(NodeIt n(_graph); n != INVALID; ++n) {
525
        if ((*_status)[n] == UNMATCHED) {
526
          (*_blossom_rep)[_blossom_set->insert(n)] = n;
527
          _tree_set->insert(n);
528
          (*_status)[n] = EVEN;
529
          processDense(n);
530
        }
531
      }
532
    }
533

	
534

	
535
    /// \brief Run Edmonds' algorithm
536
    ///
537
    /// This function runs Edmonds' algorithm. An additional heuristic of 
538
    /// postponing shrinks is used for relatively dense graphs 
539
    /// (for which <tt>m>=2*n</tt> holds).
540
    void run() {
541
      if (countEdges(_graph) < 2 * countNodes(_graph)) {
542
        greedyInit();
543
        startSparse();
544
      } else {
545
        init();
546
        startDense();
547
      }
548
    }
549

	
550
    /// @}
551

	
552
    /// \name Primal Solution
553
    /// Functions to get the primal solution, i.e. the maximum matching.
554

	
555
    /// @{
556

	
557
    /// \brief Return the size (cardinality) of the matching.
558
    ///
559
    /// This function returns the size (cardinality) of the current matching. 
560
    /// After run() it returns the size of the maximum matching in the graph.
561
    int matchingSize() const {
562
      int size = 0;
563
      for (NodeIt n(_graph); n != INVALID; ++n) {
564
        if ((*_matching)[n] != INVALID) {
565
          ++size;
566
        }
567
      }
568
      return size / 2;
569
    }
570

	
571
    /// \brief Return \c true if the given edge is in the matching.
572
    ///
573
    /// This function returns \c true if the given edge is in the current 
574
    /// matching.
575
    bool matching(const Edge& edge) const {
576
      return edge == (*_matching)[_graph.u(edge)];
577
    }
578

	
579
    /// \brief Return the matching arc (or edge) incident to the given node.
580
    ///
581
    /// This function returns the matching arc (or edge) incident to the
582
    /// given node in the current matching or \c INVALID if the node is 
583
    /// not covered by the matching.
584
    Arc matching(const Node& n) const {
585
      return (*_matching)[n];
586
    }
587

	
588
    /// \brief Return a const reference to the matching map.
589
    ///
590
    /// This function returns a const reference to a node map that stores
591
    /// the matching arc (or edge) incident to each node.
592
    const MatchingMap& matchingMap() const {
593
      return *_matching;
594
    }
595

	
596
    /// \brief Return the mate of the given node.
597
    ///
598
    /// This function returns the mate of the given node in the current 
599
    /// matching or \c INVALID if the node is not covered by the matching.
600
    Node mate(const Node& n) const {
601
      return (*_matching)[n] != INVALID ?
602
        _graph.target((*_matching)[n]) : INVALID;
603
    }
604

	
605
    /// @}
606

	
607
    /// \name Dual Solution
608
    /// Functions to get the dual solution, i.e. the Gallai-Edmonds 
609
    /// decomposition.
610

	
611
    /// @{
612

	
613
    /// \brief Return the status of the given node in the Edmonds-Gallai
614
    /// decomposition.
615
    ///
616
    /// This function returns the \ref Status "status" of the given node
617
    /// in the Edmonds-Gallai decomposition.
618
    Status status(const Node& n) const {
619
      return (*_status)[n];
620
    }
621

	
622
    /// \brief Return a const reference to the status map, which stores
623
    /// the Edmonds-Gallai decomposition.
624
    ///
625
    /// This function returns a const reference to a node map that stores the
626
    /// \ref Status "status" of each node in the Edmonds-Gallai decomposition.
627
    const StatusMap& statusMap() const {
628
      return *_status;
629
    }
630

	
631
    /// \brief Return \c true if the given node is in the barrier.
632
    ///
633
    /// This function returns \c true if the given node is in the barrier.
634
    bool barrier(const Node& n) const {
635
      return (*_status)[n] == ODD;
636
    }
637

	
638
    /// @}
639

	
640
  };
641

	
642
  /// \ingroup matching
643
  ///
644
  /// \brief Weighted matching in general graphs
645
  ///
646
  /// This class provides an efficient implementation of Edmond's
647
  /// maximum weighted matching algorithm. The implementation is based
648
  /// on extensive use of priority queues and provides
649
  /// \f$O(nm\log n)\f$ time complexity.
650
  ///
651
  /// The maximum weighted matching problem is to find a subset of the 
652
  /// edges in an undirected graph with maximum overall weight for which 
653
  /// each node has at most one incident edge.
654
  /// It can be formulated with the following linear program.
655
  /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
656
  /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
657
      \quad \forall B\in\mathcal{O}\f] */
658
  /// \f[x_e \ge 0\quad \forall e\in E\f]
659
  /// \f[\max \sum_{e\in E}x_ew_e\f]
660
  /// where \f$\delta(X)\f$ is the set of edges incident to a node in
661
  /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
662
  /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
663
  /// subsets of the nodes.
664
  ///
665
  /// The algorithm calculates an optimal matching and a proof of the
666
  /// optimality. The solution of the dual problem can be used to check
667
  /// the result of the algorithm. The dual linear problem is the
668
  /// following.
669
  /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}
670
      z_B \ge w_{uv} \quad \forall uv\in E\f] */
671
  /// \f[y_u \ge 0 \quad \forall u \in V\f]
672
  /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
673
  /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
674
      \frac{\vert B \vert - 1}{2}z_B\f] */
675
  ///
676
  /// The algorithm can be executed with the run() function. 
677
  /// After it the matching (the primal solution) and the dual solution
678
  /// can be obtained using the query functions and the 
679
  /// \ref MaxWeightedMatching::BlossomIt "BlossomIt" nested class, 
680
  /// which is able to iterate on the nodes of a blossom. 
681
  /// If the value type is integer, then the dual solution is multiplied
682
  /// by \ref MaxWeightedMatching::dualScale "4".
683
  ///
684
  /// \tparam GR The undirected graph type the algorithm runs on.
685
  /// \tparam WM The type edge weight map. The default type is 
686
  /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
687
#ifdef DOXYGEN
688
  template <typename GR, typename WM>
689
#else
690
  template <typename GR,
691
            typename WM = typename GR::template EdgeMap<int> >
692
#endif
693
  class MaxWeightedMatching {
694
  public:
695

	
696
    /// The graph type of the algorithm
697
    typedef GR Graph;
698
    /// The type of the edge weight map
699
    typedef WM WeightMap;
700
    /// The value type of the edge weights
701
    typedef typename WeightMap::Value Value;
702

	
703
    /// The type of the matching map
704
    typedef typename Graph::template NodeMap<typename Graph::Arc>
705
    MatchingMap;
706

	
707
    /// \brief Scaling factor for dual solution
708
    ///
709
    /// Scaling factor for dual solution. It is equal to 4 or 1
710
    /// according to the value type.
711
    static const int dualScale =
712
      std::numeric_limits<Value>::is_integer ? 4 : 1;
713

	
714
  private:
715

	
716
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
717

	
718
    typedef typename Graph::template NodeMap<Value> NodePotential;
719
    typedef std::vector<Node> BlossomNodeList;
720

	
721
    struct BlossomVariable {
722
      int begin, end;
723
      Value value;
724

	
725
      BlossomVariable(int _begin, int _end, Value _value)
726
        : begin(_begin), end(_end), value(_value) {}
727

	
728
    };
729

	
730
    typedef std::vector<BlossomVariable> BlossomPotential;
731

	
732
    const Graph& _graph;
733
    const WeightMap& _weight;
734

	
735
    MatchingMap* _matching;
736

	
737
    NodePotential* _node_potential;
738

	
739
    BlossomPotential _blossom_potential;
740
    BlossomNodeList _blossom_node_list;
741

	
742
    int _node_num;
743
    int _blossom_num;
744

	
745
    typedef RangeMap<int> IntIntMap;
746

	
747
    enum Status {
748
      EVEN = -1, MATCHED = 0, ODD = 1, UNMATCHED = -2
749
    };
750

	
751
    typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
752
    struct BlossomData {
753
      int tree;
754
      Status status;
755
      Arc pred, next;
756
      Value pot, offset;
757
      Node base;
758
    };
759

	
760
    IntNodeMap *_blossom_index;
761
    BlossomSet *_blossom_set;
762
    RangeMap<BlossomData>* _blossom_data;
763

	
764
    IntNodeMap *_node_index;
765
    IntArcMap *_node_heap_index;
766

	
767
    struct NodeData {
768

	
769
      NodeData(IntArcMap& node_heap_index)
770
        : heap(node_heap_index) {}
771

	
772
      int blossom;
773
      Value pot;
774
      BinHeap<Value, IntArcMap> heap;
775
      std::map<int, Arc> heap_index;
776

	
777
      int tree;
778
    };
779

	
780
    RangeMap<NodeData>* _node_data;
781

	
782
    typedef ExtendFindEnum<IntIntMap> TreeSet;
783

	
784
    IntIntMap *_tree_set_index;
785
    TreeSet *_tree_set;
786

	
787
    IntNodeMap *_delta1_index;
788
    BinHeap<Value, IntNodeMap> *_delta1;
789

	
790
    IntIntMap *_delta2_index;
791
    BinHeap<Value, IntIntMap> *_delta2;
792

	
793
    IntEdgeMap *_delta3_index;
794
    BinHeap<Value, IntEdgeMap> *_delta3;
795

	
796
    IntIntMap *_delta4_index;
797
    BinHeap<Value, IntIntMap> *_delta4;
798

	
799
    Value _delta_sum;
800

	
801
    void createStructures() {
802
      _node_num = countNodes(_graph);
803
      _blossom_num = _node_num * 3 / 2;
804

	
805
      if (!_matching) {
806
        _matching = new MatchingMap(_graph);
807
      }
808
      if (!_node_potential) {
809
        _node_potential = new NodePotential(_graph);
810
      }
811
      if (!_blossom_set) {
812
        _blossom_index = new IntNodeMap(_graph);
813
        _blossom_set = new BlossomSet(*_blossom_index);
814
        _blossom_data = new RangeMap<BlossomData>(_blossom_num);
815
      }
816

	
817
      if (!_node_index) {
818
        _node_index = new IntNodeMap(_graph);
819
        _node_heap_index = new IntArcMap(_graph);
820
        _node_data = new RangeMap<NodeData>(_node_num,
821
                                              NodeData(*_node_heap_index));
822
      }
823

	
824
      if (!_tree_set) {
825
        _tree_set_index = new IntIntMap(_blossom_num);
826
        _tree_set = new TreeSet(*_tree_set_index);
827
      }
828
      if (!_delta1) {
829
        _delta1_index = new IntNodeMap(_graph);
830
        _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
831
      }
832
      if (!_delta2) {
833
        _delta2_index = new IntIntMap(_blossom_num);
834
        _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
835
      }
836
      if (!_delta3) {
837
        _delta3_index = new IntEdgeMap(_graph);
838
        _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
839
      }
840
      if (!_delta4) {
841
        _delta4_index = new IntIntMap(_blossom_num);
842
        _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
843
      }
844
    }
845

	
846
    void destroyStructures() {
847
      _node_num = countNodes(_graph);
848
      _blossom_num = _node_num * 3 / 2;
849

	
850
      if (_matching) {
851
        delete _matching;
852
      }
853
      if (_node_potential) {
854
        delete _node_potential;
855
      }
856
      if (_blossom_set) {
857
        delete _blossom_index;
858
        delete _blossom_set;
859
        delete _blossom_data;
860
      }
861

	
862
      if (_node_index) {
863
        delete _node_index;
864
        delete _node_heap_index;
865
        delete _node_data;
866
      }
867

	
868
      if (_tree_set) {
869
        delete _tree_set_index;
870
        delete _tree_set;
871
      }
872
      if (_delta1) {
873
        delete _delta1_index;
874
        delete _delta1;
875
      }
876
      if (_delta2) {
877
        delete _delta2_index;
878
        delete _delta2;
879
      }
880
      if (_delta3) {
881
        delete _delta3_index;
882
        delete _delta3;
883
      }
884
      if (_delta4) {
885
        delete _delta4_index;
886
        delete _delta4;
887
      }
888
    }
889

	
890
    void matchedToEven(int blossom, int tree) {
891
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
892
        _delta2->erase(blossom);
893
      }
894

	
895
      if (!_blossom_set->trivial(blossom)) {
896
        (*_blossom_data)[blossom].pot -=
897
          2 * (_delta_sum - (*_blossom_data)[blossom].offset);
898
      }
899

	
900
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
901
           n != INVALID; ++n) {
902

	
903
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
904
        int ni = (*_node_index)[n];
905

	
906
        (*_node_data)[ni].heap.clear();
907
        (*_node_data)[ni].heap_index.clear();
908

	
909
        (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
910

	
911
        _delta1->push(n, (*_node_data)[ni].pot);
912

	
913
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
914
          Node v = _graph.source(e);
915
          int vb = _blossom_set->find(v);
916
          int vi = (*_node_index)[v];
917

	
918
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
919
            dualScale * _weight[e];
920

	
921
          if ((*_blossom_data)[vb].status == EVEN) {
922
            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
923
              _delta3->push(e, rw / 2);
924
            }
925
          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
926
            if (_delta3->state(e) != _delta3->IN_HEAP) {
927
              _delta3->push(e, rw);
928
            }
929
          } else {
930
            typename std::map<int, Arc>::iterator it =
931
              (*_node_data)[vi].heap_index.find(tree);
932

	
933
            if (it != (*_node_data)[vi].heap_index.end()) {
934
              if ((*_node_data)[vi].heap[it->second] > rw) {
935
                (*_node_data)[vi].heap.replace(it->second, e);
936
                (*_node_data)[vi].heap.decrease(e, rw);
937
                it->second = e;
938
              }
939
            } else {
940
              (*_node_data)[vi].heap.push(e, rw);
941
              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
942
            }
943

	
944
            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
945
              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
946

	
947
              if ((*_blossom_data)[vb].status == MATCHED) {
948
                if (_delta2->state(vb) != _delta2->IN_HEAP) {
949
                  _delta2->push(vb, _blossom_set->classPrio(vb) -
950
                               (*_blossom_data)[vb].offset);
951
                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
952
                           (*_blossom_data)[vb].offset){
953
                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
954
                                   (*_blossom_data)[vb].offset);
955
                }
956
              }
957
            }
958
          }
959
        }
960
      }
961
      (*_blossom_data)[blossom].offset = 0;
962
    }
963

	
964
    void matchedToOdd(int blossom) {
965
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
966
        _delta2->erase(blossom);
967
      }
968
      (*_blossom_data)[blossom].offset += _delta_sum;
969
      if (!_blossom_set->trivial(blossom)) {
970
        _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
971
                     (*_blossom_data)[blossom].offset);
972
      }
973
    }
974

	
975
    void evenToMatched(int blossom, int tree) {
976
      if (!_blossom_set->trivial(blossom)) {
977
        (*_blossom_data)[blossom].pot += 2 * _delta_sum;
978
      }
979

	
980
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
981
           n != INVALID; ++n) {
982
        int ni = (*_node_index)[n];
983
        (*_node_data)[ni].pot -= _delta_sum;
984

	
985
        _delta1->erase(n);
986

	
987
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
988
          Node v = _graph.source(e);
989
          int vb = _blossom_set->find(v);
990
          int vi = (*_node_index)[v];
991

	
992
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
993
            dualScale * _weight[e];
994

	
995
          if (vb == blossom) {
996
            if (_delta3->state(e) == _delta3->IN_HEAP) {
997
              _delta3->erase(e);
998
            }
999
          } else if ((*_blossom_data)[vb].status == EVEN) {
1000

	
1001
            if (_delta3->state(e) == _delta3->IN_HEAP) {
1002
              _delta3->erase(e);
1003
            }
1004

	
1005
            int vt = _tree_set->find(vb);
1006

	
1007
            if (vt != tree) {
1008

	
1009
              Arc r = _graph.oppositeArc(e);
1010

	
1011
              typename std::map<int, Arc>::iterator it =
1012
                (*_node_data)[ni].heap_index.find(vt);
1013

	
1014
              if (it != (*_node_data)[ni].heap_index.end()) {
1015
                if ((*_node_data)[ni].heap[it->second] > rw) {
1016
                  (*_node_data)[ni].heap.replace(it->second, r);
1017
                  (*_node_data)[ni].heap.decrease(r, rw);
1018
                  it->second = r;
1019
                }
1020
              } else {
1021
                (*_node_data)[ni].heap.push(r, rw);
1022
                (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
1023
              }
1024

	
1025
              if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
1026
                _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
1027

	
1028
                if (_delta2->state(blossom) != _delta2->IN_HEAP) {
1029
                  _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1030
                               (*_blossom_data)[blossom].offset);
1031
                } else if ((*_delta2)[blossom] >
1032
                           _blossom_set->classPrio(blossom) -
1033
                           (*_blossom_data)[blossom].offset){
1034
                  _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
1035
                                   (*_blossom_data)[blossom].offset);
1036
                }
1037
              }
1038
            }
1039

	
1040
          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
1041
            if (_delta3->state(e) == _delta3->IN_HEAP) {
1042
              _delta3->erase(e);
1043
            }
1044
          } else {
1045

	
1046
            typename std::map<int, Arc>::iterator it =
1047
              (*_node_data)[vi].heap_index.find(tree);
1048

	
1049
            if (it != (*_node_data)[vi].heap_index.end()) {
1050
              (*_node_data)[vi].heap.erase(it->second);
1051
              (*_node_data)[vi].heap_index.erase(it);
1052
              if ((*_node_data)[vi].heap.empty()) {
1053
                _blossom_set->increase(v, std::numeric_limits<Value>::max());
1054
              } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
1055
                _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
1056
              }
1057

	
1058
              if ((*_blossom_data)[vb].status == MATCHED) {
1059
                if (_blossom_set->classPrio(vb) ==
1060
                    std::numeric_limits<Value>::max()) {
1061
                  _delta2->erase(vb);
1062
                } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
1063
                           (*_blossom_data)[vb].offset) {
1064
                  _delta2->increase(vb, _blossom_set->classPrio(vb) -
1065
                                   (*_blossom_data)[vb].offset);
1066
                }
1067
              }
1068
            }
1069
          }
1070
        }
1071
      }
1072
    }
1073

	
1074
    void oddToMatched(int blossom) {
1075
      (*_blossom_data)[blossom].offset -= _delta_sum;
1076

	
1077
      if (_blossom_set->classPrio(blossom) !=
1078
          std::numeric_limits<Value>::max()) {
1079
        _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1080
                       (*_blossom_data)[blossom].offset);
1081
      }
1082

	
1083
      if (!_blossom_set->trivial(blossom)) {
1084
        _delta4->erase(blossom);
1085
      }
1086
    }
1087

	
1088
    void oddToEven(int blossom, int tree) {
1089
      if (!_blossom_set->trivial(blossom)) {
1090
        _delta4->erase(blossom);
1091
        (*_blossom_data)[blossom].pot -=
1092
          2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
1093
      }
1094

	
1095
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1096
           n != INVALID; ++n) {
1097
        int ni = (*_node_index)[n];
1098

	
1099
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
1100

	
1101
        (*_node_data)[ni].heap.clear();
1102
        (*_node_data)[ni].heap_index.clear();
1103
        (*_node_data)[ni].pot +=
1104
          2 * _delta_sum - (*_blossom_data)[blossom].offset;
1105

	
1106
        _delta1->push(n, (*_node_data)[ni].pot);
1107

	
1108
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
1109
          Node v = _graph.source(e);
1110
          int vb = _blossom_set->find(v);
1111
          int vi = (*_node_index)[v];
1112

	
1113
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1114
            dualScale * _weight[e];
1115

	
1116
          if ((*_blossom_data)[vb].status == EVEN) {
1117
            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
1118
              _delta3->push(e, rw / 2);
1119
            }
1120
          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
1121
            if (_delta3->state(e) != _delta3->IN_HEAP) {
1122
              _delta3->push(e, rw);
1123
            }
1124
          } else {
1125

	
1126
            typename std::map<int, Arc>::iterator it =
1127
              (*_node_data)[vi].heap_index.find(tree);
1128

	
1129
            if (it != (*_node_data)[vi].heap_index.end()) {
1130
              if ((*_node_data)[vi].heap[it->second] > rw) {
1131
                (*_node_data)[vi].heap.replace(it->second, e);
1132
                (*_node_data)[vi].heap.decrease(e, rw);
1133
                it->second = e;
1134
              }
1135
            } else {
1136
              (*_node_data)[vi].heap.push(e, rw);
1137
              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
1138
            }
1139

	
1140
            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
1141
              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
1142

	
1143
              if ((*_blossom_data)[vb].status == MATCHED) {
1144
                if (_delta2->state(vb) != _delta2->IN_HEAP) {
1145
                  _delta2->push(vb, _blossom_set->classPrio(vb) -
1146
                               (*_blossom_data)[vb].offset);
1147
                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
1148
                           (*_blossom_data)[vb].offset) {
1149
                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
1150
                                   (*_blossom_data)[vb].offset);
1151
                }
1152
              }
1153
            }
1154
          }
1155
        }
1156
      }
1157
      (*_blossom_data)[blossom].offset = 0;
1158
    }
1159

	
1160

	
1161
    void matchedToUnmatched(int blossom) {
1162
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1163
        _delta2->erase(blossom);
1164
      }
1165

	
1166
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1167
           n != INVALID; ++n) {
1168
        int ni = (*_node_index)[n];
1169

	
1170
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
1171

	
1172
        (*_node_data)[ni].heap.clear();
1173
        (*_node_data)[ni].heap_index.clear();
1174

	
1175
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1176
          Node v = _graph.target(e);
1177
          int vb = _blossom_set->find(v);
1178
          int vi = (*_node_index)[v];
1179

	
1180
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1181
            dualScale * _weight[e];
1182

	
1183
          if ((*_blossom_data)[vb].status == EVEN) {
1184
            if (_delta3->state(e) != _delta3->IN_HEAP) {
1185
              _delta3->push(e, rw);
1186
            }
1187
          }
1188
        }
1189
      }
1190
    }
1191

	
1192
    void unmatchedToMatched(int blossom) {
1193
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1194
           n != INVALID; ++n) {
1195
        int ni = (*_node_index)[n];
1196

	
1197
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
1198
          Node v = _graph.source(e);
1199
          int vb = _blossom_set->find(v);
1200
          int vi = (*_node_index)[v];
1201

	
1202
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1203
            dualScale * _weight[e];
1204

	
1205
          if (vb == blossom) {
1206
            if (_delta3->state(e) == _delta3->IN_HEAP) {
1207
              _delta3->erase(e);
1208
            }
1209
          } else if ((*_blossom_data)[vb].status == EVEN) {
1210

	
1211
            if (_delta3->state(e) == _delta3->IN_HEAP) {
1212
              _delta3->erase(e);
1213
            }
1214

	
1215
            int vt = _tree_set->find(vb);
1216

	
1217
            Arc r = _graph.oppositeArc(e);
1218

	
1219
            typename std::map<int, Arc>::iterator it =
1220
              (*_node_data)[ni].heap_index.find(vt);
1221

	
1222
            if (it != (*_node_data)[ni].heap_index.end()) {
1223
              if ((*_node_data)[ni].heap[it->second] > rw) {
1224
                (*_node_data)[ni].heap.replace(it->second, r);
1225
                (*_node_data)[ni].heap.decrease(r, rw);
1226
                it->second = r;
1227
              }
1228
            } else {
1229
              (*_node_data)[ni].heap.push(r, rw);
1230
              (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
1231
            }
1232

	
1233
            if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
1234
              _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
1235

	
1236
              if (_delta2->state(blossom) != _delta2->IN_HEAP) {
1237
                _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1238
                             (*_blossom_data)[blossom].offset);
1239
              } else if ((*_delta2)[blossom] > _blossom_set->classPrio(blossom)-
1240
                         (*_blossom_data)[blossom].offset){
1241
                _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
1242
                                 (*_blossom_data)[blossom].offset);
1243
              }
1244
            }
1245

	
1246
          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
1247
            if (_delta3->state(e) == _delta3->IN_HEAP) {
1248
              _delta3->erase(e);
1249
            }
1250
          }
1251
        }
1252
      }
1253
    }
1254

	
1255
    void alternatePath(int even, int tree) {
1256
      int odd;
1257

	
1258
      evenToMatched(even, tree);
1259
      (*_blossom_data)[even].status = MATCHED;
1260

	
1261
      while ((*_blossom_data)[even].pred != INVALID) {
1262
        odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
1263
        (*_blossom_data)[odd].status = MATCHED;
1264
        oddToMatched(odd);
1265
        (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
1266

	
1267
        even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
1268
        (*_blossom_data)[even].status = MATCHED;
1269
        evenToMatched(even, tree);
1270
        (*_blossom_data)[even].next =
1271
          _graph.oppositeArc((*_blossom_data)[odd].pred);
1272
      }
1273

	
1274
    }
1275

	
1276
    void destroyTree(int tree) {
1277
      for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
1278
        if ((*_blossom_data)[b].status == EVEN) {
1279
          (*_blossom_data)[b].status = MATCHED;
1280
          evenToMatched(b, tree);
1281
        } else if ((*_blossom_data)[b].status == ODD) {
1282
          (*_blossom_data)[b].status = MATCHED;
1283
          oddToMatched(b);
1284
        }
1285
      }
1286
      _tree_set->eraseClass(tree);
1287
    }
1288

	
1289

	
1290
    void unmatchNode(const Node& node) {
1291
      int blossom = _blossom_set->find(node);
1292
      int tree = _tree_set->find(blossom);
1293

	
1294
      alternatePath(blossom, tree);
1295
      destroyTree(tree);
1296

	
1297
      (*_blossom_data)[blossom].status = UNMATCHED;
1298
      (*_blossom_data)[blossom].base = node;
1299
      matchedToUnmatched(blossom);
1300
    }
1301

	
1302

	
1303
    void augmentOnEdge(const Edge& edge) {
1304

	
1305
      int left = _blossom_set->find(_graph.u(edge));
1306
      int right = _blossom_set->find(_graph.v(edge));
1307

	
1308
      if ((*_blossom_data)[left].status == EVEN) {
1309
        int left_tree = _tree_set->find(left);
1310
        alternatePath(left, left_tree);
1311
        destroyTree(left_tree);
1312
      } else {
1313
        (*_blossom_data)[left].status = MATCHED;
1314
        unmatchedToMatched(left);
1315
      }
1316

	
1317
      if ((*_blossom_data)[right].status == EVEN) {
1318
        int right_tree = _tree_set->find(right);
1319
        alternatePath(right, right_tree);
1320
        destroyTree(right_tree);
1321
      } else {
1322
        (*_blossom_data)[right].status = MATCHED;
1323
        unmatchedToMatched(right);
1324
      }
1325

	
1326
      (*_blossom_data)[left].next = _graph.direct(edge, true);
1327
      (*_blossom_data)[right].next = _graph.direct(edge, false);
1328
    }
1329

	
1330
    void extendOnArc(const Arc& arc) {
1331
      int base = _blossom_set->find(_graph.target(arc));
1332
      int tree = _tree_set->find(base);
1333

	
1334
      int odd = _blossom_set->find(_graph.source(arc));
1335
      _tree_set->insert(odd, tree);
1336
      (*_blossom_data)[odd].status = ODD;
1337
      matchedToOdd(odd);
1338
      (*_blossom_data)[odd].pred = arc;
1339

	
1340
      int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
1341
      (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
1342
      _tree_set->insert(even, tree);
1343
      (*_blossom_data)[even].status = EVEN;
1344
      matchedToEven(even, tree);
1345
    }
1346

	
1347
    void shrinkOnEdge(const Edge& edge, int tree) {
1348
      int nca = -1;
1349
      std::vector<int> left_path, right_path;
1350

	
1351
      {
1352
        std::set<int> left_set, right_set;
1353
        int left = _blossom_set->find(_graph.u(edge));
1354
        left_path.push_back(left);
1355
        left_set.insert(left);
1356

	
1357
        int right = _blossom_set->find(_graph.v(edge));
1358
        right_path.push_back(right);
1359
        right_set.insert(right);
1360

	
1361
        while (true) {
1362

	
1363
          if ((*_blossom_data)[left].pred == INVALID) break;
1364

	
1365
          left =
1366
            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
1367
          left_path.push_back(left);
1368
          left =
1369
            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
1370
          left_path.push_back(left);
1371

	
1372
          left_set.insert(left);
1373

	
1374
          if (right_set.find(left) != right_set.end()) {
1375
            nca = left;
1376
            break;
1377
          }
1378

	
1379
          if ((*_blossom_data)[right].pred == INVALID) break;
1380

	
1381
          right =
1382
            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
1383
          right_path.push_back(right);
1384
          right =
1385
            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
1386
          right_path.push_back(right);
1387

	
1388
          right_set.insert(right);
1389

	
1390
          if (left_set.find(right) != left_set.end()) {
1391
            nca = right;
1392
            break;
1393
          }
1394

	
1395
        }
1396

	
1397
        if (nca == -1) {
1398
          if ((*_blossom_data)[left].pred == INVALID) {
1399
            nca = right;
1400
            while (left_set.find(nca) == left_set.end()) {
1401
              nca =
1402
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1403
              right_path.push_back(nca);
1404
              nca =
1405
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1406
              right_path.push_back(nca);
1407
            }
1408
          } else {
1409
            nca = left;
1410
            while (right_set.find(nca) == right_set.end()) {
1411
              nca =
1412
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1413
              left_path.push_back(nca);
1414
              nca =
1415
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1416
              left_path.push_back(nca);
1417
            }
1418
          }
1419
        }
1420
      }
1421

	
1422
      std::vector<int> subblossoms;
1423
      Arc prev;
1424

	
1425
      prev = _graph.direct(edge, true);
1426
      for (int i = 0; left_path[i] != nca; i += 2) {
1427
        subblossoms.push_back(left_path[i]);
1428
        (*_blossom_data)[left_path[i]].next = prev;
1429
        _tree_set->erase(left_path[i]);
1430

	
1431
        subblossoms.push_back(left_path[i + 1]);
1432
        (*_blossom_data)[left_path[i + 1]].status = EVEN;
1433
        oddToEven(left_path[i + 1], tree);
1434
        _tree_set->erase(left_path[i + 1]);
1435
        prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
1436
      }
1437

	
1438
      int k = 0;
1439
      while (right_path[k] != nca) ++k;
1440

	
1441
      subblossoms.push_back(nca);
1442
      (*_blossom_data)[nca].next = prev;
1443

	
1444
      for (int i = k - 2; i >= 0; i -= 2) {
1445
        subblossoms.push_back(right_path[i + 1]);
1446
        (*_blossom_data)[right_path[i + 1]].status = EVEN;
1447
        oddToEven(right_path[i + 1], tree);
1448
        _tree_set->erase(right_path[i + 1]);
1449

	
1450
        (*_blossom_data)[right_path[i + 1]].next =
1451
          (*_blossom_data)[right_path[i + 1]].pred;
1452

	
1453
        subblossoms.push_back(right_path[i]);
1454
        _tree_set->erase(right_path[i]);
1455
      }
1456

	
1457
      int surface =
1458
        _blossom_set->join(subblossoms.begin(), subblossoms.end());
1459

	
1460
      for (int i = 0; i < int(subblossoms.size()); ++i) {
1461
        if (!_blossom_set->trivial(subblossoms[i])) {
1462
          (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
1463
        }
1464
        (*_blossom_data)[subblossoms[i]].status = MATCHED;
1465
      }
1466

	
1467
      (*_blossom_data)[surface].pot = -2 * _delta_sum;
1468
      (*_blossom_data)[surface].offset = 0;
1469
      (*_blossom_data)[surface].status = EVEN;
1470
      (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
1471
      (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
1472

	
1473
      _tree_set->insert(surface, tree);
1474
      _tree_set->erase(nca);
1475
    }
1476

	
1477
    void splitBlossom(int blossom) {
1478
      Arc next = (*_blossom_data)[blossom].next;
1479
      Arc pred = (*_blossom_data)[blossom].pred;
1480

	
1481
      int tree = _tree_set->find(blossom);
1482

	
1483
      (*_blossom_data)[blossom].status = MATCHED;
1484
      oddToMatched(blossom);
1485
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1486
        _delta2->erase(blossom);
1487
      }
1488

	
1489
      std::vector<int> subblossoms;
1490
      _blossom_set->split(blossom, std::back_inserter(subblossoms));
1491

	
1492
      Value offset = (*_blossom_data)[blossom].offset;
1493
      int b = _blossom_set->find(_graph.source(pred));
1494
      int d = _blossom_set->find(_graph.source(next));
1495

	
1496
      int ib = -1, id = -1;
1497
      for (int i = 0; i < int(subblossoms.size()); ++i) {
1498
        if (subblossoms[i] == b) ib = i;
1499
        if (subblossoms[i] == d) id = i;
1500

	
1501
        (*_blossom_data)[subblossoms[i]].offset = offset;
1502
        if (!_blossom_set->trivial(subblossoms[i])) {
1503
          (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
1504
        }
1505
        if (_blossom_set->classPrio(subblossoms[i]) !=
1506
            std::numeric_limits<Value>::max()) {
1507
          _delta2->push(subblossoms[i],
1508
                        _blossom_set->classPrio(subblossoms[i]) -
1509
                        (*_blossom_data)[subblossoms[i]].offset);
1510
        }
1511
      }
1512

	
1513
      if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
1514
        for (int i = (id + 1) % subblossoms.size();
1515
             i != ib; i = (i + 2) % subblossoms.size()) {
1516
          int sb = subblossoms[i];
1517
          int tb = subblossoms[(i + 1) % subblossoms.size()];
1518
          (*_blossom_data)[sb].next =
1519
            _graph.oppositeArc((*_blossom_data)[tb].next);
1520
        }
1521

	
1522
        for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
1523
          int sb = subblossoms[i];
1524
          int tb = subblossoms[(i + 1) % subblossoms.size()];
1525
          int ub = subblossoms[(i + 2) % subblossoms.size()];
1526

	
1527
          (*_blossom_data)[sb].status = ODD;
1528
          matchedToOdd(sb);
1529
          _tree_set->insert(sb, tree);
1530
          (*_blossom_data)[sb].pred = pred;
1531
          (*_blossom_data)[sb].next =
1532
                           _graph.oppositeArc((*_blossom_data)[tb].next);
1533

	
1534
          pred = (*_blossom_data)[ub].next;
1535

	
1536
          (*_blossom_data)[tb].status = EVEN;
1537
          matchedToEven(tb, tree);
1538
          _tree_set->insert(tb, tree);
1539
          (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
1540
        }
1541

	
1542
        (*_blossom_data)[subblossoms[id]].status = ODD;
1543
        matchedToOdd(subblossoms[id]);
1544
        _tree_set->insert(subblossoms[id], tree);
1545
        (*_blossom_data)[subblossoms[id]].next = next;
1546
        (*_blossom_data)[subblossoms[id]].pred = pred;
1547

	
1548
      } else {
1549

	
1550
        for (int i = (ib + 1) % subblossoms.size();
1551
             i != id; i = (i + 2) % subblossoms.size()) {
1552
          int sb = subblossoms[i];
1553
          int tb = subblossoms[(i + 1) % subblossoms.size()];
1554
          (*_blossom_data)[sb].next =
1555
            _graph.oppositeArc((*_blossom_data)[tb].next);
1556
        }
1557

	
1558
        for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
1559
          int sb = subblossoms[i];
1560
          int tb = subblossoms[(i + 1) % subblossoms.size()];
1561
          int ub = subblossoms[(i + 2) % subblossoms.size()];
1562

	
1563
          (*_blossom_data)[sb].status = ODD;
1564
          matchedToOdd(sb);
1565
          _tree_set->insert(sb, tree);
1566
          (*_blossom_data)[sb].next = next;
1567
          (*_blossom_data)[sb].pred =
1568
            _graph.oppositeArc((*_blossom_data)[tb].next);
1569

	
1570
          (*_blossom_data)[tb].status = EVEN;
1571
          matchedToEven(tb, tree);
1572
          _tree_set->insert(tb, tree);
1573
          (*_blossom_data)[tb].pred =
1574
            (*_blossom_data)[tb].next =
1575
            _graph.oppositeArc((*_blossom_data)[ub].next);
1576
          next = (*_blossom_data)[ub].next;
1577
        }
1578

	
1579
        (*_blossom_data)[subblossoms[ib]].status = ODD;
1580
        matchedToOdd(subblossoms[ib]);
1581
        _tree_set->insert(subblossoms[ib], tree);
1582
        (*_blossom_data)[subblossoms[ib]].next = next;
1583
        (*_blossom_data)[subblossoms[ib]].pred = pred;
1584
      }
1585
      _tree_set->erase(blossom);
1586
    }
1587

	
1588
    void extractBlossom(int blossom, const Node& base, const Arc& matching) {
1589
      if (_blossom_set->trivial(blossom)) {
1590
        int bi = (*_node_index)[base];
1591
        Value pot = (*_node_data)[bi].pot;
1592

	
1593
        (*_matching)[base] = matching;
1594
        _blossom_node_list.push_back(base);
1595
        (*_node_potential)[base] = pot;
1596
      } else {
1597

	
1598
        Value pot = (*_blossom_data)[blossom].pot;
1599
        int bn = _blossom_node_list.size();
1600

	
1601
        std::vector<int> subblossoms;
1602
        _blossom_set->split(blossom, std::back_inserter(subblossoms));
1603
        int b = _blossom_set->find(base);
1604
        int ib = -1;
1605
        for (int i = 0; i < int(subblossoms.size()); ++i) {
1606
          if (subblossoms[i] == b) { ib = i; break; }
1607
        }
1608

	
1609
        for (int i = 1; i < int(subblossoms.size()); i += 2) {
1610
          int sb = subblossoms[(ib + i) % subblossoms.size()];
1611
          int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
1612

	
1613
          Arc m = (*_blossom_data)[tb].next;
1614
          extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
1615
          extractBlossom(tb, _graph.source(m), m);
1616
        }
1617
        extractBlossom(subblossoms[ib], base, matching);
1618

	
1619
        int en = _blossom_node_list.size();
1620

	
1621
        _blossom_potential.push_back(BlossomVariable(bn, en, pot));
1622
      }
1623
    }
1624

	
1625
    void extractMatching() {
1626
      std::vector<int> blossoms;
1627
      for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
1628
        blossoms.push_back(c);
1629
      }
1630

	
1631
      for (int i = 0; i < int(blossoms.size()); ++i) {
1632
        if ((*_blossom_data)[blossoms[i]].status == MATCHED) {
1633

	
1634
          Value offset = (*_blossom_data)[blossoms[i]].offset;
1635
          (*_blossom_data)[blossoms[i]].pot += 2 * offset;
1636
          for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
1637
               n != INVALID; ++n) {
1638
            (*_node_data)[(*_node_index)[n]].pot -= offset;
1639
          }
1640

	
1641
          Arc matching = (*_blossom_data)[blossoms[i]].next;
1642
          Node base = _graph.source(matching);
1643
          extractBlossom(blossoms[i], base, matching);
1644
        } else {
1645
          Node base = (*_blossom_data)[blossoms[i]].base;
1646
          extractBlossom(blossoms[i], base, INVALID);
1647
        }
1648
      }
1649
    }
1650

	
1651
  public:
1652

	
1653
    /// \brief Constructor
1654
    ///
1655
    /// Constructor.
1656
    MaxWeightedMatching(const Graph& graph, const WeightMap& weight)
1657
      : _graph(graph), _weight(weight), _matching(0),
1658
        _node_potential(0), _blossom_potential(), _blossom_node_list(),
1659
        _node_num(0), _blossom_num(0),
1660

	
1661
        _blossom_index(0), _blossom_set(0), _blossom_data(0),
1662
        _node_index(0), _node_heap_index(0), _node_data(0),
1663
        _tree_set_index(0), _tree_set(0),
1664

	
1665
        _delta1_index(0), _delta1(0),
1666
        _delta2_index(0), _delta2(0),
1667
        _delta3_index(0), _delta3(0),
1668
        _delta4_index(0), _delta4(0),
1669

	
1670
        _delta_sum() {}
1671

	
1672
    ~MaxWeightedMatching() {
1673
      destroyStructures();
1674
    }
1675

	
1676
    /// \name Execution Control
1677
    /// The simplest way to execute the algorithm is to use the
1678
    /// \ref run() member function.
1679

	
1680
    ///@{
1681

	
1682
    /// \brief Initialize the algorithm
1683
    ///
1684
    /// This function initializes the algorithm.
1685
    void init() {
1686
      createStructures();
1687

	
1688
      for (ArcIt e(_graph); e != INVALID; ++e) {
1689
        (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
1690
      }
1691
      for (NodeIt n(_graph); n != INVALID; ++n) {
1692
        (*_delta1_index)[n] = _delta1->PRE_HEAP;
1693
      }
1694
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1695
        (*_delta3_index)[e] = _delta3->PRE_HEAP;
1696
      }
1697
      for (int i = 0; i < _blossom_num; ++i) {
1698
        (*_delta2_index)[i] = _delta2->PRE_HEAP;
1699
        (*_delta4_index)[i] = _delta4->PRE_HEAP;
1700
      }
1701

	
1702
      int index = 0;
1703
      for (NodeIt n(_graph); n != INVALID; ++n) {
1704
        Value max = 0;
1705
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1706
          if (_graph.target(e) == n) continue;
1707
          if ((dualScale * _weight[e]) / 2 > max) {
1708
            max = (dualScale * _weight[e]) / 2;
1709
          }
1710
        }
1711
        (*_node_index)[n] = index;
1712
        (*_node_data)[index].pot = max;
1713
        _delta1->push(n, max);
1714
        int blossom =
1715
          _blossom_set->insert(n, std::numeric_limits<Value>::max());
1716

	
1717
        _tree_set->insert(blossom);
1718

	
1719
        (*_blossom_data)[blossom].status = EVEN;
1720
        (*_blossom_data)[blossom].pred = INVALID;
1721
        (*_blossom_data)[blossom].next = INVALID;
1722
        (*_blossom_data)[blossom].pot = 0;
1723
        (*_blossom_data)[blossom].offset = 0;
1724
        ++index;
1725
      }
1726
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1727
        int si = (*_node_index)[_graph.u(e)];
1728
        int ti = (*_node_index)[_graph.v(e)];
1729
        if (_graph.u(e) != _graph.v(e)) {
1730
          _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
1731
                            dualScale * _weight[e]) / 2);
1732
        }
1733
      }
1734
    }
1735

	
1736
    /// \brief Start the algorithm
1737
    ///
1738
    /// This function starts the algorithm.
1739
    ///
1740
    /// \pre \ref init() must be called before using this function.
1741
    void start() {
1742
      enum OpType {
1743
        D1, D2, D3, D4
1744
      };
1745

	
1746
      int unmatched = _node_num;
1747
      while (unmatched > 0) {
1748
        Value d1 = !_delta1->empty() ?
1749
          _delta1->prio() : std::numeric_limits<Value>::max();
1750

	
1751
        Value d2 = !_delta2->empty() ?
1752
          _delta2->prio() : std::numeric_limits<Value>::max();
1753

	
1754
        Value d3 = !_delta3->empty() ?
1755
          _delta3->prio() : std::numeric_limits<Value>::max();
1756

	
1757
        Value d4 = !_delta4->empty() ?
1758
          _delta4->prio() : std::numeric_limits<Value>::max();
1759

	
1760
        _delta_sum = d1; OpType ot = D1;
1761
        if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1762
        if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
1763
        if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
1764

	
1765

	
1766
        switch (ot) {
1767
        case D1:
1768
          {
1769
            Node n = _delta1->top();
1770
            unmatchNode(n);
1771
            --unmatched;
1772
          }
1773
          break;
1774
        case D2:
1775
          {
1776
            int blossom = _delta2->top();
1777
            Node n = _blossom_set->classTop(blossom);
1778
            Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
1779
            extendOnArc(e);
1780
          }
1781
          break;
1782
        case D3:
1783
          {
1784
            Edge e = _delta3->top();
1785

	
1786
            int left_blossom = _blossom_set->find(_graph.u(e));
1787
            int right_blossom = _blossom_set->find(_graph.v(e));
1788

	
1789
            if (left_blossom == right_blossom) {
1790
              _delta3->pop();
1791
            } else {
1792
              int left_tree;
1793
              if ((*_blossom_data)[left_blossom].status == EVEN) {
1794
                left_tree = _tree_set->find(left_blossom);
1795
              } else {
1796
                left_tree = -1;
1797
                ++unmatched;
1798
              }
1799
              int right_tree;
1800
              if ((*_blossom_data)[right_blossom].status == EVEN) {
1801
                right_tree = _tree_set->find(right_blossom);
1802
              } else {
1803
                right_tree = -1;
1804
                ++unmatched;
1805
              }
1806

	
1807
              if (left_tree == right_tree) {
1808
                shrinkOnEdge(e, left_tree);
1809
              } else {
1810
                augmentOnEdge(e);
1811
                unmatched -= 2;
1812
              }
1813
            }
1814
          } break;
1815
        case D4:
1816
          splitBlossom(_delta4->top());
1817
          break;
1818
        }
1819
      }
1820
      extractMatching();
1821
    }
1822

	
1823
    /// \brief Run the algorithm.
1824
    ///
1825
    /// This method runs the \c %MaxWeightedMatching algorithm.
1826
    ///
1827
    /// \note mwm.run() is just a shortcut of the following code.
1828
    /// \code
1829
    ///   mwm.init();
1830
    ///   mwm.start();
1831
    /// \endcode
1832
    void run() {
1833
      init();
1834
      start();
1835
    }
1836

	
1837
    /// @}
1838

	
1839
    /// \name Primal Solution
1840
    /// Functions to get the primal solution, i.e. the maximum weighted 
1841
    /// matching.\n
1842
    /// Either \ref run() or \ref start() function should be called before
1843
    /// using them.
1844

	
1845
    /// @{
1846

	
1847
    /// \brief Return the weight of the matching.
1848
    ///
1849
    /// This function returns the weight of the found matching.
1850
    ///
1851
    /// \pre Either run() or start() must be called before using this function.
1852
    Value matchingWeight() const {
1853
      Value sum = 0;
1854
      for (NodeIt n(_graph); n != INVALID; ++n) {
1855
        if ((*_matching)[n] != INVALID) {
1856
          sum += _weight[(*_matching)[n]];
1857
        }
1858
      }
1859
      return sum /= 2;
1860
    }
1861

	
1862
    /// \brief Return the size (cardinality) of the matching.
1863
    ///
1864
    /// This function returns the size (cardinality) of the found matching.
1865
    ///
1866
    /// \pre Either run() or start() must be called before using this function.
1867
    int matchingSize() const {
1868
      int num = 0;
1869
      for (NodeIt n(_graph); n != INVALID; ++n) {
1870
        if ((*_matching)[n] != INVALID) {
1871
          ++num;
1872
        }
1873
      }
1874
      return num /= 2;
1875
    }
1876

	
1877
    /// \brief Return \c true if the given edge is in the matching.
1878
    ///
1879
    /// This function returns \c true if the given edge is in the found 
1880
    /// matching.
1881
    ///
1882
    /// \pre Either run() or start() must be called before using this function.
1883
    bool matching(const Edge& edge) const {
1884
      return edge == (*_matching)[_graph.u(edge)];
1885
    }
1886

	
1887
    /// \brief Return the matching arc (or edge) incident to the given node.
1888
    ///
1889
    /// This function returns the matching arc (or edge) incident to the
1890
    /// given node in the found matching or \c INVALID if the node is 
1891
    /// not covered by the matching.
1892
    ///
1893
    /// \pre Either run() or start() must be called before using this function.
1894
    Arc matching(const Node& node) const {
1895
      return (*_matching)[node];
1896
    }
1897

	
1898
    /// \brief Return a const reference to the matching map.
1899
    ///
1900
    /// This function returns a const reference to a node map that stores
1901
    /// the matching arc (or edge) incident to each node.
1902
    const MatchingMap& matchingMap() const {
1903
      return *_matching;
1904
    }
1905

	
1906
    /// \brief Return the mate of the given node.
1907
    ///
1908
    /// This function returns the mate of the given node in the found 
1909
    /// matching or \c INVALID if the node is not covered by the matching.
1910
    ///
1911
    /// \pre Either run() or start() must be called before using this function.
1912
    Node mate(const Node& node) const {
1913
      return (*_matching)[node] != INVALID ?
1914
        _graph.target((*_matching)[node]) : INVALID;
1915
    }
1916

	
1917
    /// @}
1918

	
1919
    /// \name Dual Solution
1920
    /// Functions to get the dual solution.\n
1921
    /// Either \ref run() or \ref start() function should be called before
1922
    /// using them.
1923

	
1924
    /// @{
1925

	
1926
    /// \brief Return the value of the dual solution.
1927
    ///
1928
    /// This function returns the value of the dual solution. 
1929
    /// It should be equal to the primal value scaled by \ref dualScale 
1930
    /// "dual scale".
1931
    ///
1932
    /// \pre Either run() or start() must be called before using this function.
1933
    Value dualValue() const {
1934
      Value sum = 0;
1935
      for (NodeIt n(_graph); n != INVALID; ++n) {
1936
        sum += nodeValue(n);
1937
      }
1938
      for (int i = 0; i < blossomNum(); ++i) {
1939
        sum += blossomValue(i) * (blossomSize(i) / 2);
1940
      }
1941
      return sum;
1942
    }
1943

	
1944
    /// \brief Return the dual value (potential) of the given node.
1945
    ///
1946
    /// This function returns the dual value (potential) of the given node.
1947
    ///
1948
    /// \pre Either run() or start() must be called before using this function.
1949
    Value nodeValue(const Node& n) const {
1950
      return (*_node_potential)[n];
1951
    }
1952

	
1953
    /// \brief Return the number of the blossoms in the basis.
1954
    ///
1955
    /// This function returns the number of the blossoms in the basis.
1956
    ///
1957
    /// \pre Either run() or start() must be called before using this function.
1958
    /// \see BlossomIt
1959
    int blossomNum() const {
1960
      return _blossom_potential.size();
1961
    }
1962

	
1963
    /// \brief Return the number of the nodes in the given blossom.
1964
    ///
1965
    /// This function returns the number of the nodes in the given blossom.
1966
    ///
1967
    /// \pre Either run() or start() must be called before using this function.
1968
    /// \see BlossomIt
1969
    int blossomSize(int k) const {
1970
      return _blossom_potential[k].end - _blossom_potential[k].begin;
1971
    }
1972

	
1973
    /// \brief Return the dual value (ptential) of the given blossom.
1974
    ///
1975
    /// This function returns the dual value (ptential) of the given blossom.
1976
    ///
1977
    /// \pre Either run() or start() must be called before using this function.
1978
    Value blossomValue(int k) const {
1979
      return _blossom_potential[k].value;
1980
    }
1981

	
1982
    /// \brief Iterator for obtaining the nodes of a blossom.
1983
    ///
1984
    /// This class provides an iterator for obtaining the nodes of the 
1985
    /// given blossom. It lists a subset of the nodes.
1986
    /// Before using this iterator, you must allocate a 
1987
    /// MaxWeightedMatching class and execute it.
1988
    class BlossomIt {
1989
    public:
1990

	
1991
      /// \brief Constructor.
1992
      ///
1993
      /// Constructor to get the nodes of the given variable.
1994
      ///
1995
      /// \pre Either \ref MaxWeightedMatching::run() "algorithm.run()" or 
1996
      /// \ref MaxWeightedMatching::start() "algorithm.start()" must be 
1997
      /// called before initializing this iterator.
1998
      BlossomIt(const MaxWeightedMatching& algorithm, int variable)
1999
        : _algorithm(&algorithm)
2000
      {
2001
        _index = _algorithm->_blossom_potential[variable].begin;
2002
        _last = _algorithm->_blossom_potential[variable].end;
2003
      }
2004

	
2005
      /// \brief Conversion to \c Node.
2006
      ///
2007
      /// Conversion to \c Node.
2008
      operator Node() const {
2009
        return _algorithm->_blossom_node_list[_index];
2010
      }
2011

	
2012
      /// \brief Increment operator.
2013
      ///
2014
      /// Increment operator.
2015
      BlossomIt& operator++() {
2016
        ++_index;
2017
        return *this;
2018
      }
2019

	
2020
      /// \brief Validity checking
2021
      ///
2022
      /// Checks whether the iterator is invalid.
2023
      bool operator==(Invalid) const { return _index == _last; }
2024

	
2025
      /// \brief Validity checking
2026
      ///
2027
      /// Checks whether the iterator is valid.
2028
      bool operator!=(Invalid) const { return _index != _last; }
2029

	
2030
    private:
2031
      const MaxWeightedMatching* _algorithm;
2032
      int _last;
2033
      int _index;
2034
    };
2035

	
2036
    /// @}
2037

	
2038
  };
2039

	
2040
  /// \ingroup matching
2041
  ///
2042
  /// \brief Weighted perfect matching in general graphs
2043
  ///
2044
  /// This class provides an efficient implementation of Edmond's
2045
  /// maximum weighted perfect matching algorithm. The implementation
2046
  /// is based on extensive use of priority queues and provides
2047
  /// \f$O(nm\log n)\f$ time complexity.
2048
  ///
2049
  /// The maximum weighted perfect matching problem is to find a subset of 
2050
  /// the edges in an undirected graph with maximum overall weight for which 
2051
  /// each node has exactly one incident edge.
2052
  /// It can be formulated with the following linear program.
2053
  /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
2054
  /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
2055
      \quad \forall B\in\mathcal{O}\f] */
2056
  /// \f[x_e \ge 0\quad \forall e\in E\f]
2057
  /// \f[\max \sum_{e\in E}x_ew_e\f]
2058
  /// where \f$\delta(X)\f$ is the set of edges incident to a node in
2059
  /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
2060
  /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
2061
  /// subsets of the nodes.
2062
  ///
2063
  /// The algorithm calculates an optimal matching and a proof of the
2064
  /// optimality. The solution of the dual problem can be used to check
2065
  /// the result of the algorithm. The dual linear problem is the
2066
  /// following.
2067
  /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge
2068
      w_{uv} \quad \forall uv\in E\f] */
2069
  /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
2070
  /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
2071
      \frac{\vert B \vert - 1}{2}z_B\f] */
2072
  ///
2073
  /// The algorithm can be executed with the run() function. 
2074
  /// After it the matching (the primal solution) and the dual solution
2075
  /// can be obtained using the query functions and the 
2076
  /// \ref MaxWeightedPerfectMatching::BlossomIt "BlossomIt" nested class, 
2077
  /// which is able to iterate on the nodes of a blossom. 
2078
  /// If the value type is integer, then the dual solution is multiplied
2079
  /// by \ref MaxWeightedMatching::dualScale "4".
2080
  ///
2081
  /// \tparam GR The undirected graph type the algorithm runs on.
2082
  /// \tparam WM The type edge weight map. The default type is 
2083
  /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
2084
#ifdef DOXYGEN
2085
  template <typename GR, typename WM>
2086
#else
2087
  template <typename GR,
2088
            typename WM = typename GR::template EdgeMap<int> >
2089
#endif
2090
  class MaxWeightedPerfectMatching {
2091
  public:
2092

	
2093
    /// The graph type of the algorithm
2094
    typedef GR Graph;
2095
    /// The type of the edge weight map
2096
    typedef WM WeightMap;
2097
    /// The value type of the edge weights
2098
    typedef typename WeightMap::Value Value;
2099

	
2100
    /// \brief Scaling factor for dual solution
2101
    ///
2102
    /// Scaling factor for dual solution, it is equal to 4 or 1
2103
    /// according to the value type.
2104
    static const int dualScale =
2105
      std::numeric_limits<Value>::is_integer ? 4 : 1;
2106

	
2107
    /// The type of the matching map
2108
    typedef typename Graph::template NodeMap<typename Graph::Arc>
2109
    MatchingMap;
2110

	
2111
  private:
2112

	
2113
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
2114

	
2115
    typedef typename Graph::template NodeMap<Value> NodePotential;
2116
    typedef std::vector<Node> BlossomNodeList;
2117

	
2118
    struct BlossomVariable {
2119
      int begin, end;
2120
      Value value;
2121

	
2122
      BlossomVariable(int _begin, int _end, Value _value)
2123
        : begin(_begin), end(_end), value(_value) {}
2124

	
2125
    };
2126

	
2127
    typedef std::vector<BlossomVariable> BlossomPotential;
2128

	
2129
    const Graph& _graph;
2130
    const WeightMap& _weight;
2131

	
2132
    MatchingMap* _matching;
2133

	
2134
    NodePotential* _node_potential;
2135

	
2136
    BlossomPotential _blossom_potential;
2137
    BlossomNodeList _blossom_node_list;
2138

	
2139
    int _node_num;
2140
    int _blossom_num;
2141

	
2142
    typedef RangeMap<int> IntIntMap;
2143

	
2144
    enum Status {
2145
      EVEN = -1, MATCHED = 0, ODD = 1
2146
    };
2147

	
2148
    typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
2149
    struct BlossomData {
2150
      int tree;
2151
      Status status;
2152
      Arc pred, next;
2153
      Value pot, offset;
2154
    };
2155

	
2156
    IntNodeMap *_blossom_index;
2157
    BlossomSet *_blossom_set;
2158
    RangeMap<BlossomData>* _blossom_data;
2159

	
2160
    IntNodeMap *_node_index;
2161
    IntArcMap *_node_heap_index;
2162

	
2163
    struct NodeData {
2164

	
2165
      NodeData(IntArcMap& node_heap_index)
2166
        : heap(node_heap_index) {}
2167

	
2168
      int blossom;
2169
      Value pot;
2170
      BinHeap<Value, IntArcMap> heap;
2171
      std::map<int, Arc> heap_index;
2172

	
2173
      int tree;
2174
    };
2175

	
2176
    RangeMap<NodeData>* _node_data;
2177

	
2178
    typedef ExtendFindEnum<IntIntMap> TreeSet;
2179

	
2180
    IntIntMap *_tree_set_index;
2181
    TreeSet *_tree_set;
2182

	
2183
    IntIntMap *_delta2_index;
2184
    BinHeap<Value, IntIntMap> *_delta2;
2185

	
2186
    IntEdgeMap *_delta3_index;
2187
    BinHeap<Value, IntEdgeMap> *_delta3;
2188

	
2189
    IntIntMap *_delta4_index;
2190
    BinHeap<Value, IntIntMap> *_delta4;
2191

	
2192
    Value _delta_sum;
2193

	
2194
    void createStructures() {
2195
      _node_num = countNodes(_graph);
2196
      _blossom_num = _node_num * 3 / 2;
2197

	
2198
      if (!_matching) {
2199
        _matching = new MatchingMap(_graph);
2200
      }
2201
      if (!_node_potential) {
2202
        _node_potential = new NodePotential(_graph);
2203
      }
2204
      if (!_blossom_set) {
2205
        _blossom_index = new IntNodeMap(_graph);
2206
        _blossom_set = new BlossomSet(*_blossom_index);
2207
        _blossom_data = new RangeMap<BlossomData>(_blossom_num);
2208
      }
2209

	
2210
      if (!_node_index) {
2211
        _node_index = new IntNodeMap(_graph);
2212
        _node_heap_index = new IntArcMap(_graph);
2213
        _node_data = new RangeMap<NodeData>(_node_num,
2214
                                            NodeData(*_node_heap_index));
2215
      }
2216

	
2217
      if (!_tree_set) {
2218
        _tree_set_index = new IntIntMap(_blossom_num);
2219
        _tree_set = new TreeSet(*_tree_set_index);
2220
      }
2221
      if (!_delta2) {
2222
        _delta2_index = new IntIntMap(_blossom_num);
2223
        _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
2224
      }
2225
      if (!_delta3) {
2226
        _delta3_index = new IntEdgeMap(_graph);
2227
        _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
2228
      }
2229
      if (!_delta4) {
2230
        _delta4_index = new IntIntMap(_blossom_num);
2231
        _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
2232
      }
2233
    }
2234

	
2235
    void destroyStructures() {
2236
      _node_num = countNodes(_graph);
2237
      _blossom_num = _node_num * 3 / 2;
2238

	
2239
      if (_matching) {
2240
        delete _matching;
2241
      }
2242
      if (_node_potential) {
2243
        delete _node_potential;
2244
      }
2245
      if (_blossom_set) {
2246
        delete _blossom_index;
2247
        delete _blossom_set;
2248
        delete _blossom_data;
2249
      }
2250

	
2251
      if (_node_index) {
2252
        delete _node_index;
2253
        delete _node_heap_index;
2254
        delete _node_data;
2255
      }
2256

	
2257
      if (_tree_set) {
2258
        delete _tree_set_index;
2259
        delete _tree_set;
2260
      }
2261
      if (_delta2) {
2262
        delete _delta2_index;
2263
        delete _delta2;
2264
      }
2265
      if (_delta3) {
2266
        delete _delta3_index;
2267
        delete _delta3;
2268
      }
2269
      if (_delta4) {
2270
        delete _delta4_index;
2271
        delete _delta4;
2272
      }
2273
    }
2274

	
2275
    void matchedToEven(int blossom, int tree) {
2276
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2277
        _delta2->erase(blossom);
2278
      }
2279

	
2280
      if (!_blossom_set->trivial(blossom)) {
2281
        (*_blossom_data)[blossom].pot -=
2282
          2 * (_delta_sum - (*_blossom_data)[blossom].offset);
2283
      }
2284

	
2285
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2286
           n != INVALID; ++n) {
2287

	
2288
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
2289
        int ni = (*_node_index)[n];
2290

	
2291
        (*_node_data)[ni].heap.clear();
2292
        (*_node_data)[ni].heap_index.clear();
2293

	
2294
        (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
2295

	
2296
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
2297
          Node v = _graph.source(e);
2298
          int vb = _blossom_set->find(v);
2299
          int vi = (*_node_index)[v];
2300

	
2301
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2302
            dualScale * _weight[e];
2303

	
2304
          if ((*_blossom_data)[vb].status == EVEN) {
2305
            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2306
              _delta3->push(e, rw / 2);
2307
            }
2308
          } else {
2309
            typename std::map<int, Arc>::iterator it =
2310
              (*_node_data)[vi].heap_index.find(tree);
2311

	
2312
            if (it != (*_node_data)[vi].heap_index.end()) {
2313
              if ((*_node_data)[vi].heap[it->second] > rw) {
2314
                (*_node_data)[vi].heap.replace(it->second, e);
2315
                (*_node_data)[vi].heap.decrease(e, rw);
2316
                it->second = e;
2317
              }
2318
            } else {
2319
              (*_node_data)[vi].heap.push(e, rw);
2320
              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2321
            }
2322

	
2323
            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2324
              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2325

	
2326
              if ((*_blossom_data)[vb].status == MATCHED) {
2327
                if (_delta2->state(vb) != _delta2->IN_HEAP) {
2328
                  _delta2->push(vb, _blossom_set->classPrio(vb) -
2329
                               (*_blossom_data)[vb].offset);
2330
                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2331
                           (*_blossom_data)[vb].offset){
2332
                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2333
                                   (*_blossom_data)[vb].offset);
2334
                }
2335
              }
2336
            }
2337
          }
2338
        }
2339
      }
2340
      (*_blossom_data)[blossom].offset = 0;
2341
    }
2342

	
2343
    void matchedToOdd(int blossom) {
2344
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2345
        _delta2->erase(blossom);
2346
      }
2347
      (*_blossom_data)[blossom].offset += _delta_sum;
2348
      if (!_blossom_set->trivial(blossom)) {
2349
        _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
2350
                     (*_blossom_data)[blossom].offset);
2351
      }
2352
    }
2353

	
2354
    void evenToMatched(int blossom, int tree) {
2355
      if (!_blossom_set->trivial(blossom)) {
2356
        (*_blossom_data)[blossom].pot += 2 * _delta_sum;
2357
      }
2358

	
2359
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2360
           n != INVALID; ++n) {
2361
        int ni = (*_node_index)[n];
2362
        (*_node_data)[ni].pot -= _delta_sum;
2363

	
2364
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
2365
          Node v = _graph.source(e);
2366
          int vb = _blossom_set->find(v);
2367
          int vi = (*_node_index)[v];
2368

	
2369
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2370
            dualScale * _weight[e];
2371

	
2372
          if (vb == blossom) {
2373
            if (_delta3->state(e) == _delta3->IN_HEAP) {
2374
              _delta3->erase(e);
2375
            }
2376
          } else if ((*_blossom_data)[vb].status == EVEN) {
2377

	
2378
            if (_delta3->state(e) == _delta3->IN_HEAP) {
2379
              _delta3->erase(e);
2380
            }
2381

	
2382
            int vt = _tree_set->find(vb);
2383

	
2384
            if (vt != tree) {
2385

	
2386
              Arc r = _graph.oppositeArc(e);
2387

	
2388
              typename std::map<int, Arc>::iterator it =
2389
                (*_node_data)[ni].heap_index.find(vt);
2390

	
2391
              if (it != (*_node_data)[ni].heap_index.end()) {
2392
                if ((*_node_data)[ni].heap[it->second] > rw) {
2393
                  (*_node_data)[ni].heap.replace(it->second, r);
2394
                  (*_node_data)[ni].heap.decrease(r, rw);
2395
                  it->second = r;
2396
                }
2397
              } else {
2398
                (*_node_data)[ni].heap.push(r, rw);
2399
                (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
2400
              }
2401

	
2402
              if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
2403
                _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
2404

	
2405
                if (_delta2->state(blossom) != _delta2->IN_HEAP) {
2406
                  _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2407
                               (*_blossom_data)[blossom].offset);
2408
                } else if ((*_delta2)[blossom] >
2409
                           _blossom_set->classPrio(blossom) -
2410
                           (*_blossom_data)[blossom].offset){
2411
                  _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
2412
                                   (*_blossom_data)[blossom].offset);
2413
                }
2414
              }
2415
            }
2416
          } else {
2417

	
2418
            typename std::map<int, Arc>::iterator it =
2419
              (*_node_data)[vi].heap_index.find(tree);
2420

	
2421
            if (it != (*_node_data)[vi].heap_index.end()) {
2422
              (*_node_data)[vi].heap.erase(it->second);
2423
              (*_node_data)[vi].heap_index.erase(it);
2424
              if ((*_node_data)[vi].heap.empty()) {
2425
                _blossom_set->increase(v, std::numeric_limits<Value>::max());
2426
              } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
2427
                _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
2428
              }
2429

	
2430
              if ((*_blossom_data)[vb].status == MATCHED) {
2431
                if (_blossom_set->classPrio(vb) ==
2432
                    std::numeric_limits<Value>::max()) {
2433
                  _delta2->erase(vb);
2434
                } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
2435
                           (*_blossom_data)[vb].offset) {
2436
                  _delta2->increase(vb, _blossom_set->classPrio(vb) -
2437
                                   (*_blossom_data)[vb].offset);
2438
                }
2439
              }
2440
            }
2441
          }
2442
        }
2443
      }
2444
    }
2445

	
2446
    void oddToMatched(int blossom) {
2447
      (*_blossom_data)[blossom].offset -= _delta_sum;
2448

	
2449
      if (_blossom_set->classPrio(blossom) !=
2450
          std::numeric_limits<Value>::max()) {
2451
        _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2452
                       (*_blossom_data)[blossom].offset);
2453
      }
2454

	
2455
      if (!_blossom_set->trivial(blossom)) {
2456
        _delta4->erase(blossom);
2457
      }
2458
    }
2459

	
2460
    void oddToEven(int blossom, int tree) {
2461
      if (!_blossom_set->trivial(blossom)) {
2462
        _delta4->erase(blossom);
2463
        (*_blossom_data)[blossom].pot -=
2464
          2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
2465
      }
2466

	
2467
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2468
           n != INVALID; ++n) {
2469
        int ni = (*_node_index)[n];
2470

	
2471
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
2472

	
2473
        (*_node_data)[ni].heap.clear();
2474
        (*_node_data)[ni].heap_index.clear();
2475
        (*_node_data)[ni].pot +=
2476
          2 * _delta_sum - (*_blossom_data)[blossom].offset;
2477

	
2478
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
2479
          Node v = _graph.source(e);
2480
          int vb = _blossom_set->find(v);
2481
          int vi = (*_node_index)[v];
2482

	
2483
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2484
            dualScale * _weight[e];
2485

	
2486
          if ((*_blossom_data)[vb].status == EVEN) {
2487
            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2488
              _delta3->push(e, rw / 2);
2489
            }
2490
          } else {
2491

	
2492
            typename std::map<int, Arc>::iterator it =
2493
              (*_node_data)[vi].heap_index.find(tree);
2494

	
2495
            if (it != (*_node_data)[vi].heap_index.end()) {
2496
              if ((*_node_data)[vi].heap[it->second] > rw) {
2497
                (*_node_data)[vi].heap.replace(it->second, e);
2498
                (*_node_data)[vi].heap.decrease(e, rw);
2499
                it->second = e;
2500
              }
2501
            } else {
2502
              (*_node_data)[vi].heap.push(e, rw);
2503
              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2504
            }
2505

	
2506
            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2507
              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2508

	
2509
              if ((*_blossom_data)[vb].status == MATCHED) {
2510
                if (_delta2->state(vb) != _delta2->IN_HEAP) {
2511
                  _delta2->push(vb, _blossom_set->classPrio(vb) -
2512
                               (*_blossom_data)[vb].offset);
2513
                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2514
                           (*_blossom_data)[vb].offset) {
2515
                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2516
                                   (*_blossom_data)[vb].offset);
2517
                }
2518
              }
2519
            }
2520
          }
2521
        }
2522
      }
2523
      (*_blossom_data)[blossom].offset = 0;
2524
    }
2525

	
2526
    void alternatePath(int even, int tree) {
2527
      int odd;
2528

	
2529
      evenToMatched(even, tree);
2530
      (*_blossom_data)[even].status = MATCHED;
2531

	
2532
      while ((*_blossom_data)[even].pred != INVALID) {
2533
        odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
2534
        (*_blossom_data)[odd].status = MATCHED;
2535
        oddToMatched(odd);
2536
        (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
2537

	
2538
        even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
2539
        (*_blossom_data)[even].status = MATCHED;
2540
        evenToMatched(even, tree);
2541
        (*_blossom_data)[even].next =
2542
          _graph.oppositeArc((*_blossom_data)[odd].pred);
2543
      }
2544

	
2545
    }
2546

	
2547
    void destroyTree(int tree) {
2548
      for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
2549
        if ((*_blossom_data)[b].status == EVEN) {
2550
          (*_blossom_data)[b].status = MATCHED;
2551
          evenToMatched(b, tree);
2552
        } else if ((*_blossom_data)[b].status == ODD) {
2553
          (*_blossom_data)[b].status = MATCHED;
2554
          oddToMatched(b);
2555
        }
2556
      }
2557
      _tree_set->eraseClass(tree);
2558
    }
2559

	
2560
    void augmentOnEdge(const Edge& edge) {
2561

	
2562
      int left = _blossom_set->find(_graph.u(edge));
2563
      int right = _blossom_set->find(_graph.v(edge));
2564

	
2565
      int left_tree = _tree_set->find(left);
2566
      alternatePath(left, left_tree);
2567
      destroyTree(left_tree);
2568

	
2569
      int right_tree = _tree_set->find(right);
2570
      alternatePath(right, right_tree);
2571
      destroyTree(right_tree);
2572

	
2573
      (*_blossom_data)[left].next = _graph.direct(edge, true);
2574
      (*_blossom_data)[right].next = _graph.direct(edge, false);
2575
    }
2576

	
2577
    void extendOnArc(const Arc& arc) {
2578
      int base = _blossom_set->find(_graph.target(arc));
2579
      int tree = _tree_set->find(base);
2580

	
2581
      int odd = _blossom_set->find(_graph.source(arc));
2582
      _tree_set->insert(odd, tree);
2583
      (*_blossom_data)[odd].status = ODD;
2584
      matchedToOdd(odd);
2585
      (*_blossom_data)[odd].pred = arc;
2586

	
2587
      int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
2588
      (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
2589
      _tree_set->insert(even, tree);
2590
      (*_blossom_data)[even].status = EVEN;
2591
      matchedToEven(even, tree);
2592
    }
2593

	
2594
    void shrinkOnEdge(const Edge& edge, int tree) {
2595
      int nca = -1;
2596
      std::vector<int> left_path, right_path;
2597

	
2598
      {
2599
        std::set<int> left_set, right_set;
2600
        int left = _blossom_set->find(_graph.u(edge));
2601
        left_path.push_back(left);
2602
        left_set.insert(left);
2603

	
2604
        int right = _blossom_set->find(_graph.v(edge));
2605
        right_path.push_back(right);
2606
        right_set.insert(right);
2607

	
2608
        while (true) {
2609

	
2610
          if ((*_blossom_data)[left].pred == INVALID) break;
2611

	
2612
          left =
2613
            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2614
          left_path.push_back(left);
2615
          left =
2616
            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2617
          left_path.push_back(left);
2618

	
2619
          left_set.insert(left);
2620

	
2621
          if (right_set.find(left) != right_set.end()) {
2622
            nca = left;
2623
            break;
2624
          }
2625

	
2626
          if ((*_blossom_data)[right].pred == INVALID) break;
2627

	
2628
          right =
2629
            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2630
          right_path.push_back(right);
2631
          right =
2632
            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2633
          right_path.push_back(right);
2634

	
2635
          right_set.insert(right);
2636

	
2637
          if (left_set.find(right) != left_set.end()) {
2638
            nca = right;
2639
            break;
2640
          }
2641

	
2642
        }
2643

	
2644
        if (nca == -1) {
2645
          if ((*_blossom_data)[left].pred == INVALID) {
2646
            nca = right;
2647
            while (left_set.find(nca) == left_set.end()) {
2648
              nca =
2649
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2650
              right_path.push_back(nca);
2651
              nca =
2652
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2653
              right_path.push_back(nca);
2654
            }
2655
          } else {
2656
            nca = left;
2657
            while (right_set.find(nca) == right_set.end()) {
2658
              nca =
2659
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2660
              left_path.push_back(nca);
2661
              nca =
2662
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2663
              left_path.push_back(nca);
2664
            }
2665
          }
2666
        }
2667
      }
2668

	
2669
      std::vector<int> subblossoms;
2670
      Arc prev;
2671

	
2672
      prev = _graph.direct(edge, true);
2673
      for (int i = 0; left_path[i] != nca; i += 2) {
2674
        subblossoms.push_back(left_path[i]);
2675
        (*_blossom_data)[left_path[i]].next = prev;
2676
        _tree_set->erase(left_path[i]);
2677

	
2678
        subblossoms.push_back(left_path[i + 1]);
2679
        (*_blossom_data)[left_path[i + 1]].status = EVEN;
2680
        oddToEven(left_path[i + 1], tree);
2681
        _tree_set->erase(left_path[i + 1]);
2682
        prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
2683
      }
2684

	
2685
      int k = 0;
2686
      while (right_path[k] != nca) ++k;
2687

	
2688
      subblossoms.push_back(nca);
2689
      (*_blossom_data)[nca].next = prev;
2690

	
2691
      for (int i = k - 2; i >= 0; i -= 2) {
2692
        subblossoms.push_back(right_path[i + 1]);
2693
        (*_blossom_data)[right_path[i + 1]].status = EVEN;
2694
        oddToEven(right_path[i + 1], tree);
2695
        _tree_set->erase(right_path[i + 1]);
2696

	
2697
        (*_blossom_data)[right_path[i + 1]].next =
2698
          (*_blossom_data)[right_path[i + 1]].pred;
2699

	
2700
        subblossoms.push_back(right_path[i]);
2701
        _tree_set->erase(right_path[i]);
2702
      }
2703

	
2704
      int surface =
2705
        _blossom_set->join(subblossoms.begin(), subblossoms.end());
2706

	
2707
      for (int i = 0; i < int(subblossoms.size()); ++i) {
2708
        if (!_blossom_set->trivial(subblossoms[i])) {
2709
          (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
2710
        }
2711
        (*_blossom_data)[subblossoms[i]].status = MATCHED;
2712
      }
2713

	
2714
      (*_blossom_data)[surface].pot = -2 * _delta_sum;
2715
      (*_blossom_data)[surface].offset = 0;
2716
      (*_blossom_data)[surface].status = EVEN;
2717
      (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
2718
      (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
2719

	
2720
      _tree_set->insert(surface, tree);
2721
      _tree_set->erase(nca);
2722
    }
2723

	
2724
    void splitBlossom(int blossom) {
2725
      Arc next = (*_blossom_data)[blossom].next;
2726
      Arc pred = (*_blossom_data)[blossom].pred;
2727

	
2728
      int tree = _tree_set->find(blossom);
2729

	
2730
      (*_blossom_data)[blossom].status = MATCHED;
2731
      oddToMatched(blossom);
2732
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2733
        _delta2->erase(blossom);
2734
      }
2735

	
2736
      std::vector<int> subblossoms;
2737
      _blossom_set->split(blossom, std::back_inserter(subblossoms));
2738

	
2739
      Value offset = (*_blossom_data)[blossom].offset;
2740
      int b = _blossom_set->find(_graph.source(pred));
2741
      int d = _blossom_set->find(_graph.source(next));
2742

	
2743
      int ib = -1, id = -1;
2744
      for (int i = 0; i < int(subblossoms.size()); ++i) {
2745
        if (subblossoms[i] == b) ib = i;
2746
        if (subblossoms[i] == d) id = i;
2747

	
2748
        (*_blossom_data)[subblossoms[i]].offset = offset;
2749
        if (!_blossom_set->trivial(subblossoms[i])) {
2750
          (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
2751
        }
2752
        if (_blossom_set->classPrio(subblossoms[i]) !=
2753
            std::numeric_limits<Value>::max()) {
2754
          _delta2->push(subblossoms[i],
2755
                        _blossom_set->classPrio(subblossoms[i]) -
2756
                        (*_blossom_data)[subblossoms[i]].offset);
2757
        }
2758
      }
2759

	
2760
      if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
2761
        for (int i = (id + 1) % subblossoms.size();
2762
             i != ib; i = (i + 2) % subblossoms.size()) {
2763
          int sb = subblossoms[i];
2764
          int tb = subblossoms[(i + 1) % subblossoms.size()];
2765
          (*_blossom_data)[sb].next =
2766
            _graph.oppositeArc((*_blossom_data)[tb].next);
2767
        }
2768

	
2769
        for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
2770
          int sb = subblossoms[i];
2771
          int tb = subblossoms[(i + 1) % subblossoms.size()];
2772
          int ub = subblossoms[(i + 2) % subblossoms.size()];
2773

	
2774
          (*_blossom_data)[sb].status = ODD;
2775
          matchedToOdd(sb);
2776
          _tree_set->insert(sb, tree);
2777
          (*_blossom_data)[sb].pred = pred;
2778
          (*_blossom_data)[sb].next =
2779
                           _graph.oppositeArc((*_blossom_data)[tb].next);
2780

	
2781
          pred = (*_blossom_data)[ub].next;
2782

	
2783
          (*_blossom_data)[tb].status = EVEN;
2784
          matchedToEven(tb, tree);
2785
          _tree_set->insert(tb, tree);
2786
          (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
2787
        }
2788

	
2789
        (*_blossom_data)[subblossoms[id]].status = ODD;
2790
        matchedToOdd(subblossoms[id]);
2791
        _tree_set->insert(subblossoms[id], tree);
2792
        (*_blossom_data)[subblossoms[id]].next = next;
2793
        (*_blossom_data)[subblossoms[id]].pred = pred;
2794

	
2795
      } else {
2796

	
2797
        for (int i = (ib + 1) % subblossoms.size();
2798
             i != id; i = (i + 2) % subblossoms.size()) {
2799
          int sb = subblossoms[i];
2800
          int tb = subblossoms[(i + 1) % subblossoms.size()];
2801
          (*_blossom_data)[sb].next =
2802
            _graph.oppositeArc((*_blossom_data)[tb].next);
2803
        }
2804

	
2805
        for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
2806
          int sb = subblossoms[i];
2807
          int tb = subblossoms[(i + 1) % subblossoms.size()];
2808
          int ub = subblossoms[(i + 2) % subblossoms.size()];
2809

	
2810
          (*_blossom_data)[sb].status = ODD;
2811
          matchedToOdd(sb);
2812
          _tree_set->insert(sb, tree);
2813
          (*_blossom_data)[sb].next = next;
2814
          (*_blossom_data)[sb].pred =
2815
            _graph.oppositeArc((*_blossom_data)[tb].next);
2816

	
2817
          (*_blossom_data)[tb].status = EVEN;
2818
          matchedToEven(tb, tree);
2819
          _tree_set->insert(tb, tree);
2820
          (*_blossom_data)[tb].pred =
2821
            (*_blossom_data)[tb].next =
2822
            _graph.oppositeArc((*_blossom_data)[ub].next);
2823
          next = (*_blossom_data)[ub].next;
2824
        }
2825

	
2826
        (*_blossom_data)[subblossoms[ib]].status = ODD;
2827
        matchedToOdd(subblossoms[ib]);
2828
        _tree_set->insert(subblossoms[ib], tree);
2829
        (*_blossom_data)[subblossoms[ib]].next = next;
2830
        (*_blossom_data)[subblossoms[ib]].pred = pred;
2831
      }
2832
      _tree_set->erase(blossom);
2833
    }
2834

	
2835
    void extractBlossom(int blossom, const Node& base, const Arc& matching) {
2836
      if (_blossom_set->trivial(blossom)) {
2837
        int bi = (*_node_index)[base];
2838
        Value pot = (*_node_data)[bi].pot;
2839

	
2840
        (*_matching)[base] = matching;
2841
        _blossom_node_list.push_back(base);
2842
        (*_node_potential)[base] = pot;
2843
      } else {
2844

	
2845
        Value pot = (*_blossom_data)[blossom].pot;
2846
        int bn = _blossom_node_list.size();
2847

	
2848
        std::vector<int> subblossoms;
2849
        _blossom_set->split(blossom, std::back_inserter(subblossoms));
2850
        int b = _blossom_set->find(base);
2851
        int ib = -1;
2852
        for (int i = 0; i < int(subblossoms.size()); ++i) {
2853
          if (subblossoms[i] == b) { ib = i; break; }
2854
        }
2855

	
2856
        for (int i = 1; i < int(subblossoms.size()); i += 2) {
2857
          int sb = subblossoms[(ib + i) % subblossoms.size()];
2858
          int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
2859

	
2860
          Arc m = (*_blossom_data)[tb].next;
2861
          extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
2862
          extractBlossom(tb, _graph.source(m), m);
2863
        }
2864
        extractBlossom(subblossoms[ib], base, matching);
2865

	
2866
        int en = _blossom_node_list.size();
2867

	
2868
        _blossom_potential.push_back(BlossomVariable(bn, en, pot));
2869
      }
2870
    }
2871

	
2872
    void extractMatching() {
2873
      std::vector<int> blossoms;
2874
      for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
2875
        blossoms.push_back(c);
2876
      }
2877

	
2878
      for (int i = 0; i < int(blossoms.size()); ++i) {
2879

	
2880
        Value offset = (*_blossom_data)[blossoms[i]].offset;
2881
        (*_blossom_data)[blossoms[i]].pot += 2 * offset;
2882
        for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
2883
             n != INVALID; ++n) {
2884
          (*_node_data)[(*_node_index)[n]].pot -= offset;
2885
        }
2886

	
2887
        Arc matching = (*_blossom_data)[blossoms[i]].next;
2888
        Node base = _graph.source(matching);
2889
        extractBlossom(blossoms[i], base, matching);
2890
      }
2891
    }
2892

	
2893
  public:
2894

	
2895
    /// \brief Constructor
2896
    ///
2897
    /// Constructor.
2898
    MaxWeightedPerfectMatching(const Graph& graph, const WeightMap& weight)
2899
      : _graph(graph), _weight(weight), _matching(0),
2900
        _node_potential(0), _blossom_potential(), _blossom_node_list(),
2901
        _node_num(0), _blossom_num(0),
2902

	
2903
        _blossom_index(0), _blossom_set(0), _blossom_data(0),
2904
        _node_index(0), _node_heap_index(0), _node_data(0),
2905
        _tree_set_index(0), _tree_set(0),
2906

	
2907
        _delta2_index(0), _delta2(0),
2908
        _delta3_index(0), _delta3(0),
2909
        _delta4_index(0), _delta4(0),
2910

	
2911
        _delta_sum() {}
2912

	
2913
    ~MaxWeightedPerfectMatching() {
2914
      destroyStructures();
2915
    }
2916

	
2917
    /// \name Execution Control
2918
    /// The simplest way to execute the algorithm is to use the
2919
    /// \ref run() member function.
2920

	
2921
    ///@{
2922

	
2923
    /// \brief Initialize the algorithm
2924
    ///
2925
    /// This function initializes the algorithm.
2926
    void init() {
2927
      createStructures();
2928

	
2929
      for (ArcIt e(_graph); e != INVALID; ++e) {
2930
        (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
2931
      }
2932
      for (EdgeIt e(_graph); e != INVALID; ++e) {
2933
        (*_delta3_index)[e] = _delta3->PRE_HEAP;
2934
      }
2935
      for (int i = 0; i < _blossom_num; ++i) {
2936
        (*_delta2_index)[i] = _delta2->PRE_HEAP;
2937
        (*_delta4_index)[i] = _delta4->PRE_HEAP;
2938
      }
2939

	
2940
      int index = 0;
2941
      for (NodeIt n(_graph); n != INVALID; ++n) {
2942
        Value max = - std::numeric_limits<Value>::max();
2943
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
2944
          if (_graph.target(e) == n) continue;
2945
          if ((dualScale * _weight[e]) / 2 > max) {
2946
            max = (dualScale * _weight[e]) / 2;
2947
          }
2948
        }
2949
        (*_node_index)[n] = index;
2950
        (*_node_data)[index].pot = max;
2951
        int blossom =
2952
          _blossom_set->insert(n, std::numeric_limits<Value>::max());
2953

	
2954
        _tree_set->insert(blossom);
2955

	
2956
        (*_blossom_data)[blossom].status = EVEN;
2957
        (*_blossom_data)[blossom].pred = INVALID;
2958
        (*_blossom_data)[blossom].next = INVALID;
2959
        (*_blossom_data)[blossom].pot = 0;
2960
        (*_blossom_data)[blossom].offset = 0;
2961
        ++index;
2962
      }
2963
      for (EdgeIt e(_graph); e != INVALID; ++e) {
2964
        int si = (*_node_index)[_graph.u(e)];
2965
        int ti = (*_node_index)[_graph.v(e)];
2966
        if (_graph.u(e) != _graph.v(e)) {
2967
          _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
2968
                            dualScale * _weight[e]) / 2);
2969
        }
2970
      }
2971
    }
2972

	
2973
    /// \brief Start the algorithm
2974
    ///
2975
    /// This function starts the algorithm.
2976
    ///
2977
    /// \pre \ref init() must be called before using this function.
2978
    bool start() {
2979
      enum OpType {
2980
        D2, D3, D4
2981
      };
2982

	
2983
      int unmatched = _node_num;
2984
      while (unmatched > 0) {
2985
        Value d2 = !_delta2->empty() ?
2986
          _delta2->prio() : std::numeric_limits<Value>::max();
2987

	
2988
        Value d3 = !_delta3->empty() ?
2989
          _delta3->prio() : std::numeric_limits<Value>::max();
2990

	
2991
        Value d4 = !_delta4->empty() ?
2992
          _delta4->prio() : std::numeric_limits<Value>::max();
2993

	
2994
        _delta_sum = d2; OpType ot = D2;
2995
        if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
2996
        if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
2997

	
2998
        if (_delta_sum == std::numeric_limits<Value>::max()) {
2999
          return false;
3000
        }
3001

	
3002
        switch (ot) {
3003
        case D2:
3004
          {
3005
            int blossom = _delta2->top();
3006
            Node n = _blossom_set->classTop(blossom);
3007
            Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
3008
            extendOnArc(e);
3009
          }
3010
          break;
3011
        case D3:
3012
          {
3013
            Edge e = _delta3->top();
3014

	
3015
            int left_blossom = _blossom_set->find(_graph.u(e));
3016
            int right_blossom = _blossom_set->find(_graph.v(e));
3017

	
3018
            if (left_blossom == right_blossom) {
3019
              _delta3->pop();
3020
            } else {
3021
              int left_tree = _tree_set->find(left_blossom);
3022
              int right_tree = _tree_set->find(right_blossom);
3023

	
3024
              if (left_tree == right_tree) {
3025
                shrinkOnEdge(e, left_tree);
3026
              } else {
3027
                augmentOnEdge(e);
3028
                unmatched -= 2;
3029
              }
3030
            }
3031
          } break;
3032
        case D4:
3033
          splitBlossom(_delta4->top());
3034
          break;
3035
        }
3036
      }
3037
      extractMatching();
3038
      return true;
3039
    }
3040

	
3041
    /// \brief Run the algorithm.
3042
    ///
3043
    /// This method runs the \c %MaxWeightedPerfectMatching algorithm.
3044
    ///
3045
    /// \note mwpm.run() is just a shortcut of the following code.
3046
    /// \code
3047
    ///   mwpm.init();
3048
    ///   mwpm.start();
3049
    /// \endcode
3050
    bool run() {
3051
      init();
3052
      return start();
3053
    }
3054

	
3055
    /// @}
3056

	
3057
    /// \name Primal Solution
3058
    /// Functions to get the primal solution, i.e. the maximum weighted 
3059
    /// perfect matching.\n
3060
    /// Either \ref run() or \ref start() function should be called before
3061
    /// using them.
3062

	
3063
    /// @{
3064

	
3065
    /// \brief Return the weight of the matching.
3066
    ///
3067
    /// This function returns the weight of the found matching.
3068
    ///
3069
    /// \pre Either run() or start() must be called before using this function.
3070
    Value matchingWeight() const {
3071
      Value sum = 0;
3072
      for (NodeIt n(_graph); n != INVALID; ++n) {
3073
        if ((*_matching)[n] != INVALID) {
3074
          sum += _weight[(*_matching)[n]];
3075
        }
3076
      }
3077
      return sum /= 2;
3078
    }
3079

	
3080
    /// \brief Return \c true if the given edge is in the matching.
3081
    ///
3082
    /// This function returns \c true if the given edge is in the found 
3083
    /// matching.
3084
    ///
3085
    /// \pre Either run() or start() must be called before using this function.
3086
    bool matching(const Edge& edge) const {
3087
      return static_cast<const Edge&>((*_matching)[_graph.u(edge)]) == edge;
3088
    }
3089

	
3090
    /// \brief Return the matching arc (or edge) incident to the given node.
3091
    ///
3092
    /// This function returns the matching arc (or edge) incident to the
3093
    /// given node in the found matching or \c INVALID if the node is 
3094
    /// not covered by the matching.
3095
    ///
3096
    /// \pre Either run() or start() must be called before using this function.
3097
    Arc matching(const Node& node) const {
3098
      return (*_matching)[node];
3099
    }
3100

	
3101
    /// \brief Return a const reference to the matching map.
3102
    ///
3103
    /// This function returns a const reference to a node map that stores
3104
    /// the matching arc (or edge) incident to each node.
3105
    const MatchingMap& matchingMap() const {
3106
      return *_matching;
3107
    }
3108

	
3109
    /// \brief Return the mate of the given node.
3110
    ///
3111
    /// This function returns the mate of the given node in the found 
3112
    /// matching or \c INVALID if the node is not covered by the matching.
3113
    ///
3114
    /// \pre Either run() or start() must be called before using this function.
3115
    Node mate(const Node& node) const {
3116
      return _graph.target((*_matching)[node]);
3117
    }
3118

	
3119
    /// @}
3120

	
3121
    /// \name Dual Solution
3122
    /// Functions to get the dual solution.\n
3123
    /// Either \ref run() or \ref start() function should be called before
3124
    /// using them.
3125

	
3126
    /// @{
3127

	
3128
    /// \brief Return the value of the dual solution.
3129
    ///
3130
    /// This function returns the value of the dual solution. 
3131
    /// It should be equal to the primal value scaled by \ref dualScale 
3132
    /// "dual scale".
3133
    ///
3134
    /// \pre Either run() or start() must be called before using this function.
3135
    Value dualValue() const {
3136
      Value sum = 0;
3137
      for (NodeIt n(_graph); n != INVALID; ++n) {
3138
        sum += nodeValue(n);
3139
      }
3140
      for (int i = 0; i < blossomNum(); ++i) {
3141
        sum += blossomValue(i) * (blossomSize(i) / 2);
3142
      }
3143
      return sum;
3144
    }
3145

	
3146
    /// \brief Return the dual value (potential) of the given node.
3147
    ///
3148
    /// This function returns the dual value (potential) of the given node.
3149
    ///
3150
    /// \pre Either run() or start() must be called before using this function.
3151
    Value nodeValue(const Node& n) const {
3152
      return (*_node_potential)[n];
3153
    }
3154

	
3155
    /// \brief Return the number of the blossoms in the basis.
3156
    ///
3157
    /// This function returns the number of the blossoms in the basis.
3158
    ///
3159
    /// \pre Either run() or start() must be called before using this function.
3160
    /// \see BlossomIt
3161
    int blossomNum() const {
3162
      return _blossom_potential.size();
3163
    }
3164

	
3165
    /// \brief Return the number of the nodes in the given blossom.
3166
    ///
3167
    /// This function returns the number of the nodes in the given blossom.
3168
    ///
3169
    /// \pre Either run() or start() must be called before using this function.
3170
    /// \see BlossomIt
3171
    int blossomSize(int k) const {
3172
      return _blossom_potential[k].end - _blossom_potential[k].begin;
3173
    }
3174

	
3175
    /// \brief Return the dual value (ptential) of the given blossom.
3176
    ///
3177
    /// This function returns the dual value (ptential) of the given blossom.
3178
    ///
3179
    /// \pre Either run() or start() must be called before using this function.
3180
    Value blossomValue(int k) const {
3181
      return _blossom_potential[k].value;
3182
    }
3183

	
3184
    /// \brief Iterator for obtaining the nodes of a blossom.
3185
    ///
3186
    /// This class provides an iterator for obtaining the nodes of the 
3187
    /// given blossom. It lists a subset of the nodes.
3188
    /// Before using this iterator, you must allocate a 
3189
    /// MaxWeightedPerfectMatching class and execute it.
3190
    class BlossomIt {
3191
    public:
3192

	
3193
      /// \brief Constructor.
3194
      ///
3195
      /// Constructor to get the nodes of the given variable.
3196
      ///
3197
      /// \pre Either \ref MaxWeightedPerfectMatching::run() "algorithm.run()" 
3198
      /// or \ref MaxWeightedPerfectMatching::start() "algorithm.start()" 
3199
      /// must be called before initializing this iterator.
3200
      BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable)
3201
        : _algorithm(&algorithm)
3202
      {
3203
        _index = _algorithm->_blossom_potential[variable].begin;
3204
        _last = _algorithm->_blossom_potential[variable].end;
3205
      }
3206

	
3207
      /// \brief Conversion to \c Node.
3208
      ///
3209
      /// Conversion to \c Node.
3210
      operator Node() const {
3211
        return _algorithm->_blossom_node_list[_index];
3212
      }
3213

	
3214
      /// \brief Increment operator.
3215
      ///
3216
      /// Increment operator.
3217
      BlossomIt& operator++() {
3218
        ++_index;
3219
        return *this;
3220
      }
3221

	
3222
      /// \brief Validity checking
3223
      ///
3224
      /// This function checks whether the iterator is invalid.
3225
      bool operator==(Invalid) const { return _index == _last; }
3226

	
3227
      /// \brief Validity checking
3228
      ///
3229
      /// This function checks whether the iterator is valid.
3230
      bool operator!=(Invalid) const { return _index != _last; }
3231

	
3232
    private:
3233
      const MaxWeightedPerfectMatching* _algorithm;
3234
      int _last;
3235
      int _index;
3236
    };
3237

	
3238
    /// @}
3239

	
3240
  };
3241

	
3242
} //END OF NAMESPACE LEMON
3243

	
3244
#endif //LEMON_MAX_MATCHING_H
Ignore white space 6 line context
1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library.
4
 *
5
 * Copyright (C) 2003-2009
6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8
 *
9
 * Permission to use, modify and distribute this software is granted
10
 * provided that this copyright notice appears in all copies. For
11
 * precise terms see the accompanying LICENSE file.
12
 *
13
 * This software is provided "AS IS" with no warranty of any kind,
14
 * express or implied, and with no claim as to its suitability for any
15
 * purpose.
16
 *
17
 */
18

	
19
#include <iostream>
20
#include <sstream>
21
#include <vector>
22
#include <queue>
23
#include <cstdlib>
24

	
25
#include <lemon/matching.h>
26
#include <lemon/smart_graph.h>
27
#include <lemon/concepts/graph.h>
28
#include <lemon/concepts/maps.h>
29
#include <lemon/lgf_reader.h>
30
#include <lemon/math.h>
31

	
32
#include "test_tools.h"
33

	
34
using namespace std;
35
using namespace lemon;
36

	
37
GRAPH_TYPEDEFS(SmartGraph);
38

	
39

	
40
const int lgfn = 3;
41
const std::string lgf[lgfn] = {
42
  "@nodes\n"
43
  "label\n"
44
  "0\n"
45
  "1\n"
46
  "2\n"
47
  "3\n"
48
  "4\n"
49
  "5\n"
50
  "6\n"
51
  "7\n"
52
  "@edges\n"
53
  "     label  weight\n"
54
  "7 4  0      984\n"
55
  "0 7  1      73\n"
56
  "7 1  2      204\n"
57
  "2 3  3      583\n"
58
  "2 7  4      565\n"
59
  "2 1  5      582\n"
60
  "0 4  6      551\n"
61
  "2 5  7      385\n"
62
  "1 5  8      561\n"
63
  "5 3  9      484\n"
64
  "7 5  10     904\n"
65
  "3 6  11     47\n"
66
  "7 6  12     888\n"
67
  "3 0  13     747\n"
68
  "6 1  14     310\n",
69

	
70
  "@nodes\n"
71
  "label\n"
72
  "0\n"
73
  "1\n"
74
  "2\n"
75
  "3\n"
76
  "4\n"
77
  "5\n"
78
  "6\n"
79
  "7\n"
80
  "@edges\n"
81
  "     label  weight\n"
82
  "2 5  0      710\n"
83
  "0 5  1      241\n"
84
  "2 4  2      856\n"
85
  "2 6  3      762\n"
86
  "4 1  4      747\n"
87
  "6 1  5      962\n"
88
  "4 7  6      723\n"
89
  "1 7  7      661\n"
90
  "2 3  8      376\n"
91
  "1 0  9      416\n"
92
  "6 7  10     391\n",
93

	
94
  "@nodes\n"
95
  "label\n"
96
  "0\n"
97
  "1\n"
98
  "2\n"
99
  "3\n"
100
  "4\n"
101
  "5\n"
102
  "6\n"
103
  "7\n"
104
  "@edges\n"
105
  "     label  weight\n"
106
  "6 2  0      553\n"
107
  "0 7  1      653\n"
108
  "6 3  2      22\n"
109
  "4 7  3      846\n"
110
  "7 2  4      981\n"
111
  "7 6  5      250\n"
112
  "5 2  6      539\n",
113
};
114

	
115
void checkMaxMatchingCompile()
116
{
117
  typedef concepts::Graph Graph;
118
  typedef Graph::Node Node;
119
  typedef Graph::Edge Edge;
120
  typedef Graph::EdgeMap<bool> MatMap;
121

	
122
  Graph g;
123
  Node n;
124
  Edge e;
125
  MatMap mat(g);
126

	
127
  MaxMatching<Graph> mat_test(g);
128
  const MaxMatching<Graph>&
129
    const_mat_test = mat_test;
130

	
131
  mat_test.init();
132
  mat_test.greedyInit();
133
  mat_test.matchingInit(mat);
134
  mat_test.startSparse();
135
  mat_test.startDense();
136
  mat_test.run();
137
  
138
  const_mat_test.matchingSize();
139
  const_mat_test.matching(e);
140
  const_mat_test.matching(n);
141
  const MaxMatching<Graph>::MatchingMap& mmap =
142
    const_mat_test.matchingMap();
143
  e = mmap[n];
144
  const_mat_test.mate(n);
145

	
146
  MaxMatching<Graph>::Status stat = 
147
    const_mat_test.status(n);
148
  const MaxMatching<Graph>::StatusMap& smap =
149
    const_mat_test.statusMap();
150
  stat = smap[n];
151
  const_mat_test.barrier(n);
152
}
153

	
154
void checkMaxWeightedMatchingCompile()
155
{
156
  typedef concepts::Graph Graph;
157
  typedef Graph::Node Node;
158
  typedef Graph::Edge Edge;
159
  typedef Graph::EdgeMap<int> WeightMap;
160

	
161
  Graph g;
162
  Node n;
163
  Edge e;
164
  WeightMap w(g);
165

	
166
  MaxWeightedMatching<Graph> mat_test(g, w);
167
  const MaxWeightedMatching<Graph>&
168
    const_mat_test = mat_test;
169

	
170
  mat_test.init();
171
  mat_test.start();
172
  mat_test.run();
173
  
174
  const_mat_test.matchingWeight();
175
  const_mat_test.matchingSize();
176
  const_mat_test.matching(e);
177
  const_mat_test.matching(n);
178
  const MaxWeightedMatching<Graph>::MatchingMap& mmap =
179
    const_mat_test.matchingMap();
180
  e = mmap[n];
181
  const_mat_test.mate(n);
182
  
183
  int k = 0;
184
  const_mat_test.dualValue();
185
  const_mat_test.nodeValue(n);
186
  const_mat_test.blossomNum();
187
  const_mat_test.blossomSize(k);
188
  const_mat_test.blossomValue(k);
189
}
190

	
191
void checkMaxWeightedPerfectMatchingCompile()
192
{
193
  typedef concepts::Graph Graph;
194
  typedef Graph::Node Node;
195
  typedef Graph::Edge Edge;
196
  typedef Graph::EdgeMap<int> WeightMap;
197

	
198
  Graph g;
199
  Node n;
200
  Edge e;
201
  WeightMap w(g);
202

	
203
  MaxWeightedPerfectMatching<Graph> mat_test(g, w);
204
  const MaxWeightedPerfectMatching<Graph>&
205
    const_mat_test = mat_test;
206

	
207
  mat_test.init();
208
  mat_test.start();
209
  mat_test.run();
210
  
211
  const_mat_test.matchingWeight();
212
  const_mat_test.matching(e);
213
  const_mat_test.matching(n);
214
  const MaxWeightedPerfectMatching<Graph>::MatchingMap& mmap =
215
    const_mat_test.matchingMap();
216
  e = mmap[n];
217
  const_mat_test.mate(n);
218
  
219
  int k = 0;
220
  const_mat_test.dualValue();
221
  const_mat_test.nodeValue(n);
222
  const_mat_test.blossomNum();
223
  const_mat_test.blossomSize(k);
224
  const_mat_test.blossomValue(k);
225
}
226

	
227
void checkMatching(const SmartGraph& graph,
228
                   const MaxMatching<SmartGraph>& mm) {
229
  int num = 0;
230

	
231
  IntNodeMap comp_index(graph);
232
  UnionFind<IntNodeMap> comp(comp_index);
233

	
234
  int barrier_num = 0;
235

	
236
  for (NodeIt n(graph); n != INVALID; ++n) {
237
    check(mm.status(n) == MaxMatching<SmartGraph>::EVEN ||
238
          mm.matching(n) != INVALID, "Wrong Gallai-Edmonds decomposition");
239
    if (mm.status(n) == MaxMatching<SmartGraph>::ODD) {
240
      ++barrier_num;
241
    } else {
242
      comp.insert(n);
243
    }
244
  }
245

	
246
  for (EdgeIt e(graph); e != INVALID; ++e) {
247
    if (mm.matching(e)) {
248
      check(e == mm.matching(graph.u(e)), "Wrong matching");
249
      check(e == mm.matching(graph.v(e)), "Wrong matching");
250
      ++num;
251
    }
252
    check(mm.status(graph.u(e)) != MaxMatching<SmartGraph>::EVEN ||
253
          mm.status(graph.v(e)) != MaxMatching<SmartGraph>::MATCHED,
254
          "Wrong Gallai-Edmonds decomposition");
255

	
256
    check(mm.status(graph.v(e)) != MaxMatching<SmartGraph>::EVEN ||
257
          mm.status(graph.u(e)) != MaxMatching<SmartGraph>::MATCHED,
258
          "Wrong Gallai-Edmonds decomposition");
259

	
260
    if (mm.status(graph.u(e)) != MaxMatching<SmartGraph>::ODD &&
261
        mm.status(graph.v(e)) != MaxMatching<SmartGraph>::ODD) {
262
      comp.join(graph.u(e), graph.v(e));
263
    }
264
  }
265

	
266
  std::set<int> comp_root;
267
  int odd_comp_num = 0;
268
  for (NodeIt n(graph); n != INVALID; ++n) {
269
    if (mm.status(n) != MaxMatching<SmartGraph>::ODD) {
270
      int root = comp.find(n);
271
      if (comp_root.find(root) == comp_root.end()) {
272
        comp_root.insert(root);
273
        if (comp.size(n) % 2 == 1) {
274
          ++odd_comp_num;
275
        }
276
      }
277
    }
278
  }
279

	
280
  check(mm.matchingSize() == num, "Wrong matching");
281
  check(2 * num == countNodes(graph) - (odd_comp_num - barrier_num),
282
         "Wrong matching");
283
  return;
284
}
285

	
286
void checkWeightedMatching(const SmartGraph& graph,
287
                   const SmartGraph::EdgeMap<int>& weight,
288
                   const MaxWeightedMatching<SmartGraph>& mwm) {
289
  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
290
    if (graph.u(e) == graph.v(e)) continue;
291
    int rw = mwm.nodeValue(graph.u(e)) + mwm.nodeValue(graph.v(e));
292

	
293
    for (int i = 0; i < mwm.blossomNum(); ++i) {
294
      bool s = false, t = false;
295
      for (MaxWeightedMatching<SmartGraph>::BlossomIt n(mwm, i);
296
           n != INVALID; ++n) {
297
        if (graph.u(e) == n) s = true;
298
        if (graph.v(e) == n) t = true;
299
      }
300
      if (s == true && t == true) {
301
        rw += mwm.blossomValue(i);
302
      }
303
    }
304
    rw -= weight[e] * mwm.dualScale;
305

	
306
    check(rw >= 0, "Negative reduced weight");
307
    check(rw == 0 || !mwm.matching(e),
308
          "Non-zero reduced weight on matching edge");
309
  }
310

	
311
  int pv = 0;
312
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
313
    if (mwm.matching(n) != INVALID) {
314
      check(mwm.nodeValue(n) >= 0, "Invalid node value");
315
      pv += weight[mwm.matching(n)];
316
      SmartGraph::Node o = graph.target(mwm.matching(n));
317
      check(mwm.mate(n) == o, "Invalid matching");
318
      check(mwm.matching(n) == graph.oppositeArc(mwm.matching(o)),
319
            "Invalid matching");
320
    } else {
321
      check(mwm.mate(n) == INVALID, "Invalid matching");
322
      check(mwm.nodeValue(n) == 0, "Invalid matching");
323
    }
324
  }
325

	
326
  int dv = 0;
327
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
328
    dv += mwm.nodeValue(n);
329
  }
330

	
331
  for (int i = 0; i < mwm.blossomNum(); ++i) {
332
    check(mwm.blossomValue(i) >= 0, "Invalid blossom value");
333
    check(mwm.blossomSize(i) % 2 == 1, "Even blossom size");
334
    dv += mwm.blossomValue(i) * ((mwm.blossomSize(i) - 1) / 2);
335
  }
336

	
337
  check(pv * mwm.dualScale == dv * 2, "Wrong duality");
338

	
339
  return;
340
}
341

	
342
void checkWeightedPerfectMatching(const SmartGraph& graph,
343
                          const SmartGraph::EdgeMap<int>& weight,
344
                          const MaxWeightedPerfectMatching<SmartGraph>& mwpm) {
345
  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
346
    if (graph.u(e) == graph.v(e)) continue;
347
    int rw = mwpm.nodeValue(graph.u(e)) + mwpm.nodeValue(graph.v(e));
348

	
349
    for (int i = 0; i < mwpm.blossomNum(); ++i) {
350
      bool s = false, t = false;
351
      for (MaxWeightedPerfectMatching<SmartGraph>::BlossomIt n(mwpm, i);
352
           n != INVALID; ++n) {
353
        if (graph.u(e) == n) s = true;
354
        if (graph.v(e) == n) t = true;
355
      }
356
      if (s == true && t == true) {
357
        rw += mwpm.blossomValue(i);
358
      }
359
    }
360
    rw -= weight[e] * mwpm.dualScale;
361

	
362
    check(rw >= 0, "Negative reduced weight");
363
    check(rw == 0 || !mwpm.matching(e),
364
          "Non-zero reduced weight on matching edge");
365
  }
366

	
367
  int pv = 0;
368
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
369
    check(mwpm.matching(n) != INVALID, "Non perfect");
370
    pv += weight[mwpm.matching(n)];
371
    SmartGraph::Node o = graph.target(mwpm.matching(n));
372
    check(mwpm.mate(n) == o, "Invalid matching");
373
    check(mwpm.matching(n) == graph.oppositeArc(mwpm.matching(o)),
374
          "Invalid matching");
375
  }
376

	
377
  int dv = 0;
378
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
379
    dv += mwpm.nodeValue(n);
380
  }
381

	
382
  for (int i = 0; i < mwpm.blossomNum(); ++i) {
383
    check(mwpm.blossomValue(i) >= 0, "Invalid blossom value");
384
    check(mwpm.blossomSize(i) % 2 == 1, "Even blossom size");
385
    dv += mwpm.blossomValue(i) * ((mwpm.blossomSize(i) - 1) / 2);
386
  }
387

	
388
  check(pv * mwpm.dualScale == dv * 2, "Wrong duality");
389

	
390
  return;
391
}
392

	
393

	
394
int main() {
395

	
396
  for (int i = 0; i < lgfn; ++i) {
397
    SmartGraph graph;
398
    SmartGraph::EdgeMap<int> weight(graph);
399

	
400
    istringstream lgfs(lgf[i]);
401
    graphReader(graph, lgfs).
402
      edgeMap("weight", weight).run();
403

	
404
    MaxMatching<SmartGraph> mm(graph);
405
    mm.run();
406
    checkMatching(graph, mm);
407

	
408
    MaxWeightedMatching<SmartGraph> mwm(graph, weight);
409
    mwm.run();
410
    checkWeightedMatching(graph, weight, mwm);
411

	
412
    MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight);
413
    bool perfect = mwpm.run();
414

	
415
    check(perfect == (mm.matchingSize() * 2 == countNodes(graph)),
416
          "Perfect matching found");
417

	
418
    if (perfect) {
419
      checkWeightedPerfectMatching(graph, weight, mwpm);
420
    }
421
  }
422

	
423
  return 0;
424
}
Ignore white space 6 line context
... ...
@@ -432,15 +432,16 @@
432 432

	
433 433
/**
434 434
@defgroup matching Matching Algorithms
435 435
@ingroup algs
436 436
\brief Algorithms for finding matchings in graphs and bipartite graphs.
437 437

	
438
This group contains algorithm objects and functions to calculate
438
This group contains the algorithms for calculating
439 439
matchings in graphs and bipartite graphs. The general matching problem is
440
finding a subset of the arcs which does not shares common endpoints.
440
finding a subset of the edges for which each node has at most one incident
441
edge.
441 442

	
442 443
There are several different algorithms for calculate matchings in
443 444
graphs.  The matching problems in bipartite graphs are generally
444 445
easier than in general graphs. The goal of the matching optimization
445 446
can be finding maximum cardinality, maximum weight or minimum cost
446 447
matching. The search can be constrained to find perfect or
Ignore white space 6 line context
... ...
@@ -86,14 +86,14 @@
86 86
	lemon/list_graph.h \
87 87
	lemon/lp.h \
88 88
	lemon/lp_base.h \
89 89
	lemon/lp_skeleton.h \
90 90
	lemon/list_graph.h \
91 91
	lemon/maps.h \
92
	lemon/matching.h \
92 93
	lemon/math.h \
93
	lemon/max_matching.h \
94 94
	lemon/min_cost_arborescence.h \
95 95
	lemon/nauty_reader.h \
96 96
	lemon/path.h \
97 97
	lemon/preflow.h \
98 98
	lemon/radix_sort.h \
99 99
	lemon/random.h \
Ignore white space 6 line context
... ...
@@ -23,224 +23,247 @@
23 23
#include<lemon/adaptors.h>
24 24
#include<lemon/connectivity.h>
25 25
#include <list>
26 26

	
27 27
/// \ingroup graph_properties
28 28
/// \file
29
/// \brief Euler tour
29
/// \brief Euler tour iterators and a function for checking the \e Eulerian 
30
/// property.
30 31
///
31
///This file provides an Euler tour iterator and ways to check
32
///if a digraph is euler.
33

	
32
///This file provides Euler tour iterators and a function to check
33
///if a (di)graph is \e Eulerian.
34 34

	
35 35
namespace lemon {
36 36

	
37
  ///Euler iterator for digraphs.
37
  ///Euler tour iterator for digraphs.
38 38

	
39
  /// \ingroup graph_properties
40
  ///This iterator converts to the \c Arc type of the digraph and using
41
  ///operator ++, it provides an Euler tour of a \e directed
42
  ///graph (if there exists).
39
  /// \ingroup graph_prop
40
  ///This iterator provides an Euler tour (Eulerian circuit) of a \e directed
41
  ///graph (if there exists) and it converts to the \c Arc type of the digraph.
43 42
  ///
44
  ///For example
45
  ///if the given digraph is Euler (i.e it has only one nontrivial component
46
  ///and the in-degree is equal to the out-degree for all nodes),
47
  ///the following code will put the arcs of \c g
48
  ///to the vector \c et according to an
49
  ///Euler tour of \c g.
43
  ///For example, if the given digraph has an Euler tour (i.e it has only one
44
  ///non-trivial component and the in-degree is equal to the out-degree 
45
  ///for all nodes), then the following code will put the arcs of \c g
46
  ///to the vector \c et according to an Euler tour of \c g.
50 47
  ///\code
51 48
  ///  std::vector<ListDigraph::Arc> et;
52
  ///  for(DiEulerIt<ListDigraph> e(g),e!=INVALID;++e)
49
  ///  for(DiEulerIt<ListDigraph> e(g); e!=INVALID; ++e)
53 50
  ///    et.push_back(e);
54 51
  ///\endcode
55
  ///If \c g is not Euler then the resulted tour will not be full or closed.
52
  ///If \c g has no Euler tour, then the resulted walk will not be closed
53
  ///or not contain all arcs.
56 54
  ///\sa EulerIt
57 55
  template<typename GR>
58 56
  class DiEulerIt
59 57
  {
60 58
    typedef typename GR::Node Node;
61 59
    typedef typename GR::NodeIt NodeIt;
62 60
    typedef typename GR::Arc Arc;
63 61
    typedef typename GR::ArcIt ArcIt;
64 62
    typedef typename GR::OutArcIt OutArcIt;
65 63
    typedef typename GR::InArcIt InArcIt;
66 64

	
67 65
    const GR &g;
68
    typename GR::template NodeMap<OutArcIt> nedge;
66
    typename GR::template NodeMap<OutArcIt> narc;
69 67
    std::list<Arc> euler;
70 68

	
71 69
  public:
72 70

	
73 71
    ///Constructor
74 72

	
73
    ///Constructor.
75 74
    ///\param gr A digraph.
76
    ///\param start The starting point of the tour. If it is not given
77
    ///       the tour will start from the first node.
75
    ///\param start The starting point of the tour. If it is not given,
76
    ///the tour will start from the first node that has an outgoing arc.
78 77
    DiEulerIt(const GR &gr, typename GR::Node start = INVALID)
79
      : g(gr), nedge(g)
78
      : g(gr), narc(g)
80 79
    {
81
      if(start==INVALID) start=NodeIt(g);
82
      for(NodeIt n(g);n!=INVALID;++n) nedge[n]=OutArcIt(g,n);
83
      while(nedge[start]!=INVALID) {
84
        euler.push_back(nedge[start]);
85
        Node next=g.target(nedge[start]);
86
        ++nedge[start];
87
        start=next;
80
      if (start==INVALID) {
81
        NodeIt n(g);
82
        while (n!=INVALID && OutArcIt(g,n)==INVALID) ++n;
83
        start=n;
84
      }
85
      if (start!=INVALID) {
86
        for (NodeIt n(g); n!=INVALID; ++n) narc[n]=OutArcIt(g,n);
87
        while (narc[start]!=INVALID) {
88
          euler.push_back(narc[start]);
89
          Node next=g.target(narc[start]);
90
          ++narc[start];
91
          start=next;
92
        }
88 93
      }
89 94
    }
90 95

	
91
    ///Arc Conversion
96
    ///Arc conversion
92 97
    operator Arc() { return euler.empty()?INVALID:euler.front(); }
98
    ///Compare with \c INVALID
93 99
    bool operator==(Invalid) { return euler.empty(); }
100
    ///Compare with \c INVALID
94 101
    bool operator!=(Invalid) { return !euler.empty(); }
95 102

	
96 103
    ///Next arc of the tour
104

	
105
    ///Next arc of the tour
106
    ///
97 107
    DiEulerIt &operator++() {
98 108
      Node s=g.target(euler.front());
99 109
      euler.pop_front();
100
      //This produces a warning.Strange.
101
      //std::list<Arc>::iterator next=euler.begin();
102 110
      typename std::list<Arc>::iterator next=euler.begin();
103
      while(nedge[s]!=INVALID) {
104
        euler.insert(next,nedge[s]);
105
        Node n=g.target(nedge[s]);
106
        ++nedge[s];
111
      while(narc[s]!=INVALID) {
112
        euler.insert(next,narc[s]);
113
        Node n=g.target(narc[s]);
114
        ++narc[s];
107 115
        s=n;
108 116
      }
109 117
      return *this;
110 118
    }
111 119
    ///Postfix incrementation
112 120

	
121
    /// Postfix incrementation.
122
    ///
113 123
    ///\warning This incrementation
114
    ///returns an \c Arc, not an \ref DiEulerIt, as one may
124
    ///returns an \c Arc, not a \ref DiEulerIt, as one may
115 125
    ///expect.
116 126
    Arc operator++(int)
117 127
    {
118 128
      Arc e=*this;
119 129
      ++(*this);
120 130
      return e;
121 131
    }
122 132
  };
123 133

	
124
  ///Euler iterator for graphs.
134
  ///Euler tour iterator for graphs.
125 135

	
126 136
  /// \ingroup graph_properties
127
  ///This iterator converts to the \c Arc (or \c Edge)
128
  ///type of the digraph and using
129
  ///operator ++, it provides an Euler tour of an undirected
130
  ///digraph (if there exists).
137
  ///This iterator provides an Euler tour (Eulerian circuit) of an
138
  ///\e undirected graph (if there exists) and it converts to the \c Arc
139
  ///and \c Edge types of the graph.
131 140
  ///
132
  ///For example
133
  ///if the given digraph if Euler (i.e it has only one nontrivial component
134
  ///and the degree of each node is even),
141
  ///For example, if the given graph has an Euler tour (i.e it has only one 
142
  ///non-trivial component and the degree of each node is even),
135 143
  ///the following code will print the arc IDs according to an
136 144
  ///Euler tour of \c g.
137 145
  ///\code
138
  ///  for(EulerIt<ListGraph> e(g),e!=INVALID;++e) {
146
  ///  for(EulerIt<ListGraph> e(g); e!=INVALID; ++e) {
139 147
  ///    std::cout << g.id(Edge(e)) << std::eol;
140 148
  ///  }
141 149
  ///\endcode
142
  ///Although the iterator provides an Euler tour of an graph,
143
  ///it still returns Arcs in order to indicate the direction of the tour.
144
  ///(But Arc will convert to Edges, of course).
150
  ///Although this iterator is for undirected graphs, it still returns 
151
  ///arcs in order to indicate the direction of the tour.
152
  ///(But arcs convert to edges, of course.)
145 153
  ///
146
  ///If \c g is not Euler then the resulted tour will not be full or closed.
147
  ///\sa EulerIt
154
  ///If \c g has no Euler tour, then the resulted walk will not be closed
155
  ///or not contain all edges.
148 156
  template<typename GR>
149 157
  class EulerIt
150 158
  {
151 159
    typedef typename GR::Node Node;
152 160
    typedef typename GR::NodeIt NodeIt;
153 161
    typedef typename GR::Arc Arc;
154 162
    typedef typename GR::Edge Edge;
155 163
    typedef typename GR::ArcIt ArcIt;
156 164
    typedef typename GR::OutArcIt OutArcIt;
157 165
    typedef typename GR::InArcIt InArcIt;
158 166

	
159 167
    const GR &g;
160
    typename GR::template NodeMap<OutArcIt> nedge;
168
    typename GR::template NodeMap<OutArcIt> narc;
161 169
    typename GR::template EdgeMap<bool> visited;
162 170
    std::list<Arc> euler;
163 171

	
164 172
  public:
165 173

	
166 174
    ///Constructor
167 175

	
168
    ///\param gr An graph.
169
    ///\param start The starting point of the tour. If it is not given
170
    ///       the tour will start from the first node.
176
    ///Constructor.
177
    ///\param gr A graph.
178
    ///\param start The starting point of the tour. If it is not given,
179
    ///the tour will start from the first node that has an incident edge.
171 180
    EulerIt(const GR &gr, typename GR::Node start = INVALID)
172
      : g(gr), nedge(g), visited(g, false)
181
      : g(gr), narc(g), visited(g, false)
173 182
    {
174
      if(start==INVALID) start=NodeIt(g);
175
      for(NodeIt n(g);n!=INVALID;++n) nedge[n]=OutArcIt(g,n);
176
      while(nedge[start]!=INVALID) {
177
        euler.push_back(nedge[start]);
178
        visited[nedge[start]]=true;
179
        Node next=g.target(nedge[start]);
180
        ++nedge[start];
181
        start=next;
182
        while(nedge[start]!=INVALID && visited[nedge[start]]) ++nedge[start];
183
      if (start==INVALID) {
184
        NodeIt n(g);
185
        while (n!=INVALID && OutArcIt(g,n)==INVALID) ++n;
186
        start=n;
187
      }
188
      if (start!=INVALID) {
189
        for (NodeIt n(g); n!=INVALID; ++n) narc[n]=OutArcIt(g,n);
190
        while(narc[start]!=INVALID) {
191
          euler.push_back(narc[start]);
192
          visited[narc[start]]=true;
193
          Node next=g.target(narc[start]);
194
          ++narc[start];
195
          start=next;
196
          while(narc[start]!=INVALID && visited[narc[start]]) ++narc[start];
197
        }
183 198
      }
184 199
    }
185 200

	
186
    ///Arc Conversion
201
    ///Arc conversion
187 202
    operator Arc() const { return euler.empty()?INVALID:euler.front(); }
188
    ///Arc Conversion
203
    ///Edge conversion
189 204
    operator Edge() const { return euler.empty()?INVALID:euler.front(); }
190
    ///\e
205
    ///Compare with \c INVALID
191 206
    bool operator==(Invalid) const { return euler.empty(); }
192
    ///\e
207
    ///Compare with \c INVALID
193 208
    bool operator!=(Invalid) const { return !euler.empty(); }
194 209

	
195 210
    ///Next arc of the tour
211

	
212
    ///Next arc of the tour
213
    ///
196 214
    EulerIt &operator++() {
197 215
      Node s=g.target(euler.front());
198 216
      euler.pop_front();
199 217
      typename std::list<Arc>::iterator next=euler.begin();
200

	
201
      while(nedge[s]!=INVALID) {
202
        while(nedge[s]!=INVALID && visited[nedge[s]]) ++nedge[s];
203
        if(nedge[s]==INVALID) break;
218
      while(narc[s]!=INVALID) {
219
        while(narc[s]!=INVALID && visited[narc[s]]) ++narc[s];
220
        if(narc[s]==INVALID) break;
204 221
        else {
205
          euler.insert(next,nedge[s]);
206
          visited[nedge[s]]=true;
207
          Node n=g.target(nedge[s]);
208
          ++nedge[s];
222
          euler.insert(next,narc[s]);
223
          visited[narc[s]]=true;
224
          Node n=g.target(narc[s]);
225
          ++narc[s];
209 226
          s=n;
210 227
        }
211 228
      }
212 229
      return *this;
213 230
    }
214 231

	
215 232
    ///Postfix incrementation
216 233

	
217
    ///\warning This incrementation
218
    ///returns an \c Arc, not an \ref EulerIt, as one may
219
    ///expect.
234
    /// Postfix incrementation.
235
    ///
236
    ///\warning This incrementation returns an \c Arc (which converts to 
237
    ///an \c Edge), not an \ref EulerIt, as one may expect.
220 238
    Arc operator++(int)
221 239
    {
222 240
      Arc e=*this;
223 241
      ++(*this);
224 242
      return e;
225 243
    }
226 244
  };
227 245

	
228 246

	
229
  ///Checks if the graph is Eulerian
247
  ///Check if the given graph is \e Eulerian
230 248

	
231 249
  /// \ingroup graph_properties
232
  ///Checks if the graph is Eulerian. It works for both directed and undirected
233
  ///graphs.
234
  ///\note By definition, a digraph is called \e Eulerian if
235
  ///and only if it is connected and the number of its incoming and outgoing
250
  ///This function checks if the given graph is \e Eulerian.
251
  ///It works for both directed and undirected graphs.
252
  ///
253
  ///By definition, a digraph is called \e Eulerian if
254
  ///and only if it is connected and the number of incoming and outgoing
236 255
  ///arcs are the same for each node.
237 256
  ///Similarly, an undirected graph is called \e Eulerian if
238
  ///and only if it is connected and the number of incident arcs is even
239
  ///for each node. <em>Therefore, there are digraphs which are not Eulerian,
240
  ///but still have an Euler tour</em>.
257
  ///and only if it is connected and the number of incident edges is even
258
  ///for each node.
259
  ///
260
  ///\note There are (di)graphs that are not Eulerian, but still have an
261
  /// Euler tour, since they may contain isolated nodes.
262
  ///
263
  ///\sa DiEulerIt, EulerIt
241 264
  template<typename GR>
242 265
#ifdef DOXYGEN
243 266
  bool
244 267
#else
245 268
  typename enable_if<UndirectedTagIndicator<GR>,bool>::type
246 269
  eulerian(const GR &g)
... ...
@@ -253,12 +276,12 @@
253 276
  typename disable_if<UndirectedTagIndicator<GR>,bool>::type
254 277
#endif
255 278
  eulerian(const GR &g)
256 279
  {
257 280
    for(typename GR::NodeIt n(g);n!=INVALID;++n)
258 281
      if(countInArcs(g,n)!=countOutArcs(g,n)) return false;
259
    return connected(Undirector<const GR>(g));
282
    return connected(undirector(g));
260 283
  }
261 284

	
262 285
}
263 286

	
264 287
#endif
Ignore white space 6 line context
... ...
@@ -26,13 +26,13 @@
26 26
  graph_test
27 27
  graph_utils_test
28 28
  hao_orlin_test
29 29
  heap_test
30 30
  kruskal_test
31 31
  maps_test
32
  max_matching_test
32
  matching_test
33 33
  min_cost_arborescence_test
34 34
  path_test
35 35
  preflow_test
36 36
  radix_sort_test
37 37
  random_test
38 38
  suurballe_test
Ignore white space 6 line context
... ...
@@ -22,13 +22,13 @@
22 22
	test/graph_test \
23 23
	test/graph_utils_test \
24 24
	test/hao_orlin_test \
25 25
	test/heap_test \
26 26
	test/kruskal_test \
27 27
	test/maps_test \
28
	test/max_matching_test \
28
	test/matching_test \
29 29
	test/min_cost_arborescence_test \
30 30
	test/path_test \
31 31
	test/preflow_test \
32 32
	test/radix_sort_test \
33 33
	test/random_test \
34 34
	test/suurballe_test \
... ...
@@ -67,13 +67,13 @@
67 67
test_heap_test_SOURCES = test/heap_test.cc
68 68
test_kruskal_test_SOURCES = test/kruskal_test.cc
69 69
test_hao_orlin_test_SOURCES = test/hao_orlin_test.cc
70 70
test_lp_test_SOURCES = test/lp_test.cc
71 71
test_maps_test_SOURCES = test/maps_test.cc
72 72
test_mip_test_SOURCES = test/mip_test.cc
73
test_max_matching_test_SOURCES = test/max_matching_test.cc
73
test_matching_test_SOURCES = test/matching_test.cc
74 74
test_min_cost_arborescence_test_SOURCES = test/min_cost_arborescence_test.cc
75 75
test_path_test_SOURCES = test/path_test.cc
76 76
test_preflow_test_SOURCES = test/preflow_test.cc
77 77
test_radix_sort_test_SOURCES = test/radix_sort_test.cc
78 78
test_suurballe_test_SOURCES = test/suurballe_test.cc
79 79
test_random_test_SOURCES = test/random_test.cc
Ignore white space 6 line context
... ...
@@ -15,139 +15,209 @@
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#include <lemon/euler.h>
20 20
#include <lemon/list_graph.h>
21
#include <test/test_tools.h>
21
#include <lemon/adaptors.h>
22
#include "test_tools.h"
22 23

	
23 24
using namespace lemon;
24 25

	
25 26
template <typename Digraph>
26
void checkDiEulerIt(const Digraph& g)
27
void checkDiEulerIt(const Digraph& g,
28
                    const typename Digraph::Node& start = INVALID)
27 29
{
28 30
  typename Digraph::template ArcMap<int> visitationNumber(g, 0);
29 31

	
30
  DiEulerIt<Digraph> e(g);
32
  DiEulerIt<Digraph> e(g, start);
33
  if (e == INVALID) return;
31 34
  typename Digraph::Node firstNode = g.source(e);
32 35
  typename Digraph::Node lastNode = g.target(e);
36
  if (start != INVALID) {
37
    check(firstNode == start, "checkDiEulerIt: Wrong first node");
38
  }
33 39

	
34
  for (; e != INVALID; ++e)
35
  {
36
    if (e != INVALID)
37
    {
38
      lastNode = g.target(e);
39
    }
40
  for (; e != INVALID; ++e) {
41
    if (e != INVALID) lastNode = g.target(e);
40 42
    ++visitationNumber[e];
41 43
  }
42 44

	
43 45
  check(firstNode == lastNode,
44
      "checkDiEulerIt: first and last node are not the same");
46
      "checkDiEulerIt: First and last nodes are not the same");
45 47

	
46 48
  for (typename Digraph::ArcIt a(g); a != INVALID; ++a)
47 49
  {
48 50
    check(visitationNumber[a] == 1,
49
        "checkDiEulerIt: not visited or multiple times visited arc found");
51
        "checkDiEulerIt: Not visited or multiple times visited arc found");
50 52
  }
51 53
}
52 54

	
53 55
template <typename Graph>
54
void checkEulerIt(const Graph& g)
56
void checkEulerIt(const Graph& g,
57
                  const typename Graph::Node& start = INVALID)
55 58
{
56 59
  typename Graph::template EdgeMap<int> visitationNumber(g, 0);
57 60

	
58
  EulerIt<Graph> e(g);
59
  typename Graph::Node firstNode = g.u(e);
60
  typename Graph::Node lastNode = g.v(e);
61
  EulerIt<Graph> e(g, start);
62
  if (e == INVALID) return;
63
  typename Graph::Node firstNode = g.source(typename Graph::Arc(e));
64
  typename Graph::Node lastNode = g.target(typename Graph::Arc(e));
65
  if (start != INVALID) {
66
    check(firstNode == start, "checkEulerIt: Wrong first node");
67
  }
61 68

	
62
  for (; e != INVALID; ++e)
63
  {
64
    if (e != INVALID)
65
    {
66
      lastNode = g.v(e);
67
    }
69
  for (; e != INVALID; ++e) {
70
    if (e != INVALID) lastNode = g.target(typename Graph::Arc(e));
68 71
    ++visitationNumber[e];
69 72
  }
70 73

	
71 74
  check(firstNode == lastNode,
72
      "checkEulerIt: first and last node are not the same");
75
      "checkEulerIt: First and last nodes are not the same");
73 76

	
74 77
  for (typename Graph::EdgeIt e(g); e != INVALID; ++e)
75 78
  {
76 79
    check(visitationNumber[e] == 1,
77
        "checkEulerIt: not visited or multiple times visited edge found");
80
        "checkEulerIt: Not visited or multiple times visited edge found");
78 81
  }
79 82
}
80 83

	
81 84
int main()
82 85
{
83 86
  typedef ListDigraph Digraph;
84
  typedef ListGraph Graph;
87
  typedef Undirector<Digraph> Graph;
88
  
89
  {
90
    Digraph d;
91
    Graph g(d);
92
    
93
    checkDiEulerIt(d);
94
    checkDiEulerIt(g);
95
    checkEulerIt(g);
85 96

	
86
  Digraph digraphWithEulerianCircuit;
97
    check(eulerian(d), "This graph is Eulerian");
98
    check(eulerian(g), "This graph is Eulerian");
99
  }
87 100
  {
88
    Digraph& g = digraphWithEulerianCircuit;
101
    Digraph d;
102
    Graph g(d);
103
    Digraph::Node n = d.addNode();
89 104

	
90
    Digraph::Node n0 = g.addNode();
91
    Digraph::Node n1 = g.addNode();
92
    Digraph::Node n2 = g.addNode();
105
    checkDiEulerIt(d);
106
    checkDiEulerIt(g);
107
    checkEulerIt(g);
93 108

	
94
    g.addArc(n0, n1);
95
    g.addArc(n1, n0);
96
    g.addArc(n1, n2);
97
    g.addArc(n2, n1);
109
    check(eulerian(d), "This graph is Eulerian");
110
    check(eulerian(g), "This graph is Eulerian");
98 111
  }
112
  {
113
    Digraph d;
114
    Graph g(d);
115
    Digraph::Node n = d.addNode();
116
    d.addArc(n, n);
99 117

	
100
  Digraph digraphWithoutEulerianCircuit;
118
    checkDiEulerIt(d);
119
    checkDiEulerIt(g);
120
    checkEulerIt(g);
121

	
122
    check(eulerian(d), "This graph is Eulerian");
123
    check(eulerian(g), "This graph is Eulerian");
124
  }
101 125
  {
102
    Digraph& g = digraphWithoutEulerianCircuit;
126
    Digraph d;
127
    Graph g(d);
128
    Digraph::Node n1 = d.addNode();
129
    Digraph::Node n2 = d.addNode();
130
    Digraph::Node n3 = d.addNode();
131
    
132
    d.addArc(n1, n2);
133
    d.addArc(n2, n1);
134
    d.addArc(n2, n3);
135
    d.addArc(n3, n2);
103 136

	
104
    Digraph::Node n0 = g.addNode();
105
    Digraph::Node n1 = g.addNode();
106
    Digraph::Node n2 = g.addNode();
137
    checkDiEulerIt(d);
138
    checkDiEulerIt(d, n2);
139
    checkDiEulerIt(g);
140
    checkDiEulerIt(g, n2);
141
    checkEulerIt(g);
142
    checkEulerIt(g, n2);
107 143

	
108
    g.addArc(n0, n1);
109
    g.addArc(n1, n0);
110
    g.addArc(n1, n2);
144
    check(eulerian(d), "This graph is Eulerian");
145
    check(eulerian(g), "This graph is Eulerian");
111 146
  }
147
  {
148
    Digraph d;
149
    Graph g(d);
150
    Digraph::Node n1 = d.addNode();
151
    Digraph::Node n2 = d.addNode();
152
    Digraph::Node n3 = d.addNode();
153
    Digraph::Node n4 = d.addNode();
154
    Digraph::Node n5 = d.addNode();
155
    Digraph::Node n6 = d.addNode();
156
    
157
    d.addArc(n1, n2);
158
    d.addArc(n2, n4);
159
    d.addArc(n1, n3);
160
    d.addArc(n3, n4);
161
    d.addArc(n4, n1);
162
    d.addArc(n3, n5);
163
    d.addArc(n5, n2);
164
    d.addArc(n4, n6);
165
    d.addArc(n2, n6);
166
    d.addArc(n6, n1);
167
    d.addArc(n6, n3);
112 168

	
113
  Graph graphWithEulerianCircuit;
169
    checkDiEulerIt(d);
170
    checkDiEulerIt(d, n1);
171
    checkDiEulerIt(d, n5);
172

	
173
    checkDiEulerIt(g);
174
    checkDiEulerIt(g, n1);
175
    checkDiEulerIt(g, n5);
176
    checkEulerIt(g);
177
    checkEulerIt(g, n1);
178
    checkEulerIt(g, n5);
179

	
180
    check(eulerian(d), "This graph is Eulerian");
181
    check(eulerian(g), "This graph is Eulerian");
182
  }
114 183
  {
115
    Graph& g = graphWithEulerianCircuit;
184
    Digraph d;
185
    Graph g(d);
186
    Digraph::Node n0 = d.addNode();
187
    Digraph::Node n1 = d.addNode();
188
    Digraph::Node n2 = d.addNode();
189
    Digraph::Node n3 = d.addNode();
190
    Digraph::Node n4 = d.addNode();
191
    Digraph::Node n5 = d.addNode();
192
    
193
    d.addArc(n1, n2);
194
    d.addArc(n2, n3);
195
    d.addArc(n3, n1);
116 196

	
117
    Graph::Node n0 = g.addNode();
118
    Graph::Node n1 = g.addNode();
119
    Graph::Node n2 = g.addNode();
197
    checkDiEulerIt(d);
198
    checkDiEulerIt(d, n2);
120 199

	
121
    g.addEdge(n0, n1);
122
    g.addEdge(n1, n2);
123
    g.addEdge(n2, n0);
200
    checkDiEulerIt(g);
201
    checkDiEulerIt(g, n2);
202
    checkEulerIt(g);
203
    checkEulerIt(g, n2);
204

	
205
    check(!eulerian(d), "This graph is not Eulerian");
206
    check(!eulerian(g), "This graph is not Eulerian");
124 207
  }
208
  {
209
    Digraph d;
210
    Graph g(d);
211
    Digraph::Node n1 = d.addNode();
212
    Digraph::Node n2 = d.addNode();
213
    Digraph::Node n3 = d.addNode();
214
    
215
    d.addArc(n1, n2);
216
    d.addArc(n2, n3);
125 217

	
126
  Graph graphWithoutEulerianCircuit;
127
  {
128
    Graph& g = graphWithoutEulerianCircuit;
129

	
130
    Graph::Node n0 = g.addNode();
131
    Graph::Node n1 = g.addNode();
132
    Graph::Node n2 = g.addNode();
133

	
134
    g.addEdge(n0, n1);
135
    g.addEdge(n1, n2);
218
    check(!eulerian(d), "This graph is not Eulerian");
219
    check(!eulerian(g), "This graph is not Eulerian");
136 220
  }
137 221

	
138
  checkDiEulerIt(digraphWithEulerianCircuit);
139

	
140
  checkEulerIt(graphWithEulerianCircuit);
141

	
142
  check(eulerian(digraphWithEulerianCircuit),
143
      "this graph should have an Eulerian circuit");
144
  check(!eulerian(digraphWithoutEulerianCircuit),
145
      "this graph should not have an Eulerian circuit");
146

	
147
  check(eulerian(graphWithEulerianCircuit),
148
      "this graph should have an Eulerian circuit");
149
  check(!eulerian(graphWithoutEulerianCircuit),
150
      "this graph should have an Eulerian circuit");
151

	
152 222
  return 0;
153 223
}
Ignore white space 6 line context
... ...
@@ -39,13 +39,13 @@
39 39

	
40 40
#include <lemon/arg_parser.h>
41 41
#include <lemon/error.h>
42 42

	
43 43
#include <lemon/dijkstra.h>
44 44
#include <lemon/preflow.h>
45
#include <lemon/max_matching.h>
45
#include <lemon/matching.h>
46 46

	
47 47
using namespace lemon;
48 48
typedef SmartDigraph Digraph;
49 49
DIGRAPH_TYPEDEFS(Digraph);
50 50
typedef SmartGraph Graph;
51 51

	
Ignore white space 6 line context
1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library.
4
 *
5
 * Copyright (C) 2003-2009
6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8
 *
9
 * Permission to use, modify and distribute this software is granted
10
 * provided that this copyright notice appears in all copies. For
11
 * precise terms see the accompanying LICENSE file.
12
 *
13
 * This software is provided "AS IS" with no warranty of any kind,
14
 * express or implied, and with no claim as to its suitability for any
15
 * purpose.
16
 *
17
 */
18

	
19
#ifndef LEMON_MAX_MATCHING_H
20
#define LEMON_MAX_MATCHING_H
21

	
22
#include <vector>
23
#include <queue>
24
#include <set>
25
#include <limits>
26

	
27
#include <lemon/core.h>
28
#include <lemon/unionfind.h>
29
#include <lemon/bin_heap.h>
30
#include <lemon/maps.h>
31

	
32
///\ingroup matching
33
///\file
34
///\brief Maximum matching algorithms in general graphs.
35

	
36
namespace lemon {
37

	
38
  /// \ingroup matching
39
  ///
40
  /// \brief Edmonds' alternating forest maximum matching algorithm.
41
  ///
42
  /// This class implements Edmonds' alternating forest matching
43
  /// algorithm. The algorithm can be started from an arbitrary initial
44
  /// matching (the default is the empty one)
45
  ///
46
  /// The dual solution of the problem is a map of the nodes to
47
  /// MaxMatching::Status, having values \c EVEN/D, \c ODD/A and \c
48
  /// MATCHED/C showing the Gallai-Edmonds decomposition of the
49
  /// graph. The nodes in \c EVEN/D induce a graph with
50
  /// factor-critical components, the nodes in \c ODD/A form the
51
  /// barrier, and the nodes in \c MATCHED/C induce a graph having a
52
  /// perfect matching. The number of the factor-critical components
53
  /// minus the number of barrier nodes is a lower bound on the
54
  /// unmatched nodes, and the matching is optimal if and only if this bound is
55
  /// tight. This decomposition can be attained by calling \c
56
  /// decomposition() after running the algorithm.
57
  ///
58
  /// \param GR The graph type the algorithm runs on.
59
  template <typename GR>
60
  class MaxMatching {
61
  public:
62

	
63
    typedef GR Graph;
64
    typedef typename Graph::template NodeMap<typename Graph::Arc>
65
    MatchingMap;
66

	
67
    ///\brief Indicates the Gallai-Edmonds decomposition of the graph.
68
    ///
69
    ///Indicates the Gallai-Edmonds decomposition of the graph. The
70
    ///nodes with Status \c EVEN/D induce a graph with factor-critical
71
    ///components, the nodes in \c ODD/A form the canonical barrier,
72
    ///and the nodes in \c MATCHED/C induce a graph having a perfect
73
    ///matching.
74
    enum Status {
75
      EVEN = 1, D = 1, MATCHED = 0, C = 0, ODD = -1, A = -1, UNMATCHED = -2
76
    };
77

	
78
    typedef typename Graph::template NodeMap<Status> StatusMap;
79

	
80
  private:
81

	
82
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
83

	
84
    typedef UnionFindEnum<IntNodeMap> BlossomSet;
85
    typedef ExtendFindEnum<IntNodeMap> TreeSet;
86
    typedef RangeMap<Node> NodeIntMap;
87
    typedef MatchingMap EarMap;
88
    typedef std::vector<Node> NodeQueue;
89

	
90
    const Graph& _graph;
91
    MatchingMap* _matching;
92
    StatusMap* _status;
93

	
94
    EarMap* _ear;
95

	
96
    IntNodeMap* _blossom_set_index;
97
    BlossomSet* _blossom_set;
98
    NodeIntMap* _blossom_rep;
99

	
100
    IntNodeMap* _tree_set_index;
101
    TreeSet* _tree_set;
102

	
103
    NodeQueue _node_queue;
104
    int _process, _postpone, _last;
105

	
106
    int _node_num;
107

	
108
  private:
109

	
110
    void createStructures() {
111
      _node_num = countNodes(_graph);
112
      if (!_matching) {
113
        _matching = new MatchingMap(_graph);
114
      }
115
      if (!_status) {
116
        _status = new StatusMap(_graph);
117
      }
118
      if (!_ear) {
119
        _ear = new EarMap(_graph);
120
      }
121
      if (!_blossom_set) {
122
        _blossom_set_index = new IntNodeMap(_graph);
123
        _blossom_set = new BlossomSet(*_blossom_set_index);
124
      }
125
      if (!_blossom_rep) {
126
        _blossom_rep = new NodeIntMap(_node_num);
127
      }
128
      if (!_tree_set) {
129
        _tree_set_index = new IntNodeMap(_graph);
130
        _tree_set = new TreeSet(*_tree_set_index);
131
      }
132
      _node_queue.resize(_node_num);
133
    }
134

	
135
    void destroyStructures() {
136
      if (_matching) {
137
        delete _matching;
138
      }
139
      if (_status) {
140
        delete _status;
141
      }
142
      if (_ear) {
143
        delete _ear;
144
      }
145
      if (_blossom_set) {
146
        delete _blossom_set;
147
        delete _blossom_set_index;
148
      }
149
      if (_blossom_rep) {
150
        delete _blossom_rep;
151
      }
152
      if (_tree_set) {
153
        delete _tree_set_index;
154
        delete _tree_set;
155
      }
156
    }
157

	
158
    void processDense(const Node& n) {
159
      _process = _postpone = _last = 0;
160
      _node_queue[_last++] = n;
161

	
162
      while (_process != _last) {
163
        Node u = _node_queue[_process++];
164
        for (OutArcIt a(_graph, u); a != INVALID; ++a) {
165
          Node v = _graph.target(a);
166
          if ((*_status)[v] == MATCHED) {
167
            extendOnArc(a);
168
          } else if ((*_status)[v] == UNMATCHED) {
169
            augmentOnArc(a);
170
            return;
171
          }
172
        }
173
      }
174

	
175
      while (_postpone != _last) {
176
        Node u = _node_queue[_postpone++];
177

	
178
        for (OutArcIt a(_graph, u); a != INVALID ; ++a) {
179
          Node v = _graph.target(a);
180

	
181
          if ((*_status)[v] == EVEN) {
182
            if (_blossom_set->find(u) != _blossom_set->find(v)) {
183
              shrinkOnEdge(a);
184
            }
185
          }
186

	
187
          while (_process != _last) {
188
            Node w = _node_queue[_process++];
189
            for (OutArcIt b(_graph, w); b != INVALID; ++b) {
190
              Node x = _graph.target(b);
191
              if ((*_status)[x] == MATCHED) {
192
                extendOnArc(b);
193
              } else if ((*_status)[x] == UNMATCHED) {
194
                augmentOnArc(b);
195
                return;
196
              }
197
            }
198
          }
199
        }
200
      }
201
    }
202

	
203
    void processSparse(const Node& n) {
204
      _process = _last = 0;
205
      _node_queue[_last++] = n;
206
      while (_process != _last) {
207
        Node u = _node_queue[_process++];
208
        for (OutArcIt a(_graph, u); a != INVALID; ++a) {
209
          Node v = _graph.target(a);
210

	
211
          if ((*_status)[v] == EVEN) {
212
            if (_blossom_set->find(u) != _blossom_set->find(v)) {
213
              shrinkOnEdge(a);
214
            }
215
          } else if ((*_status)[v] == MATCHED) {
216
            extendOnArc(a);
217
          } else if ((*_status)[v] == UNMATCHED) {
218
            augmentOnArc(a);
219
            return;
220
          }
221
        }
222
      }
223
    }
224

	
225
    void shrinkOnEdge(const Edge& e) {
226
      Node nca = INVALID;
227

	
228
      {
229
        std::set<Node> left_set, right_set;
230

	
231
        Node left = (*_blossom_rep)[_blossom_set->find(_graph.u(e))];
232
        left_set.insert(left);
233

	
234
        Node right = (*_blossom_rep)[_blossom_set->find(_graph.v(e))];
235
        right_set.insert(right);
236

	
237
        while (true) {
238
          if ((*_matching)[left] == INVALID) break;
239
          left = _graph.target((*_matching)[left]);
240
          left = (*_blossom_rep)[_blossom_set->
241
                                 find(_graph.target((*_ear)[left]))];
242
          if (right_set.find(left) != right_set.end()) {
243
            nca = left;
244
            break;
245
          }
246
          left_set.insert(left);
247

	
248
          if ((*_matching)[right] == INVALID) break;
249
          right = _graph.target((*_matching)[right]);
250
          right = (*_blossom_rep)[_blossom_set->
251
                                  find(_graph.target((*_ear)[right]))];
252
          if (left_set.find(right) != left_set.end()) {
253
            nca = right;
254
            break;
255
          }
256
          right_set.insert(right);
257
        }
258

	
259
        if (nca == INVALID) {
260
          if ((*_matching)[left] == INVALID) {
261
            nca = right;
262
            while (left_set.find(nca) == left_set.end()) {
263
              nca = _graph.target((*_matching)[nca]);
264
              nca =(*_blossom_rep)[_blossom_set->
265
                                   find(_graph.target((*_ear)[nca]))];
266
            }
267
          } else {
268
            nca = left;
269
            while (right_set.find(nca) == right_set.end()) {
270
              nca = _graph.target((*_matching)[nca]);
271
              nca = (*_blossom_rep)[_blossom_set->
272
                                   find(_graph.target((*_ear)[nca]))];
273
            }
274
          }
275
        }
276
      }
277

	
278
      {
279

	
280
        Node node = _graph.u(e);
281
        Arc arc = _graph.direct(e, true);
282
        Node base = (*_blossom_rep)[_blossom_set->find(node)];
283

	
284
        while (base != nca) {
285
          (*_ear)[node] = arc;
286

	
287
          Node n = node;
288
          while (n != base) {
289
            n = _graph.target((*_matching)[n]);
290
            Arc a = (*_ear)[n];
291
            n = _graph.target(a);
292
            (*_ear)[n] = _graph.oppositeArc(a);
293
          }
294
          node = _graph.target((*_matching)[base]);
295
          _tree_set->erase(base);
296
          _tree_set->erase(node);
297
          _blossom_set->insert(node, _blossom_set->find(base));
298
          (*_status)[node] = EVEN;
299
          _node_queue[_last++] = node;
300
          arc = _graph.oppositeArc((*_ear)[node]);
301
          node = _graph.target((*_ear)[node]);
302
          base = (*_blossom_rep)[_blossom_set->find(node)];
303
          _blossom_set->join(_graph.target(arc), base);
304
        }
305
      }
306

	
307
      (*_blossom_rep)[_blossom_set->find(nca)] = nca;
308

	
309
      {
310

	
311
        Node node = _graph.v(e);
312
        Arc arc = _graph.direct(e, false);
313
        Node base = (*_blossom_rep)[_blossom_set->find(node)];
314

	
315
        while (base != nca) {
316
          (*_ear)[node] = arc;
317

	
318
          Node n = node;
319
          while (n != base) {
320
            n = _graph.target((*_matching)[n]);
321
            Arc a = (*_ear)[n];
322
            n = _graph.target(a);
323
            (*_ear)[n] = _graph.oppositeArc(a);
324
          }
325
          node = _graph.target((*_matching)[base]);
326
          _tree_set->erase(base);
327
          _tree_set->erase(node);
328
          _blossom_set->insert(node, _blossom_set->find(base));
329
          (*_status)[node] = EVEN;
330
          _node_queue[_last++] = node;
331
          arc = _graph.oppositeArc((*_ear)[node]);
332
          node = _graph.target((*_ear)[node]);
333
          base = (*_blossom_rep)[_blossom_set->find(node)];
334
          _blossom_set->join(_graph.target(arc), base);
335
        }
336
      }
337

	
338
      (*_blossom_rep)[_blossom_set->find(nca)] = nca;
339
    }
340

	
341

	
342

	
343
    void extendOnArc(const Arc& a) {
344
      Node base = _graph.source(a);
345
      Node odd = _graph.target(a);
346

	
347
      (*_ear)[odd] = _graph.oppositeArc(a);
348
      Node even = _graph.target((*_matching)[odd]);
349
      (*_blossom_rep)[_blossom_set->insert(even)] = even;
350
      (*_status)[odd] = ODD;
351
      (*_status)[even] = EVEN;
352
      int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(base)]);
353
      _tree_set->insert(odd, tree);
354
      _tree_set->insert(even, tree);
355
      _node_queue[_last++] = even;
356

	
357
    }
358

	
359
    void augmentOnArc(const Arc& a) {
360
      Node even = _graph.source(a);
361
      Node odd = _graph.target(a);
362

	
363
      int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(even)]);
364

	
365
      (*_matching)[odd] = _graph.oppositeArc(a);
366
      (*_status)[odd] = MATCHED;
367

	
368
      Arc arc = (*_matching)[even];
369
      (*_matching)[even] = a;
370

	
371
      while (arc != INVALID) {
372
        odd = _graph.target(arc);
373
        arc = (*_ear)[odd];
374
        even = _graph.target(arc);
375
        (*_matching)[odd] = arc;
376
        arc = (*_matching)[even];
377
        (*_matching)[even] = _graph.oppositeArc((*_matching)[odd]);
378
      }
379

	
380
      for (typename TreeSet::ItemIt it(*_tree_set, tree);
381
           it != INVALID; ++it) {
382
        if ((*_status)[it] == ODD) {
383
          (*_status)[it] = MATCHED;
384
        } else {
385
          int blossom = _blossom_set->find(it);
386
          for (typename BlossomSet::ItemIt jt(*_blossom_set, blossom);
387
               jt != INVALID; ++jt) {
388
            (*_status)[jt] = MATCHED;
389
          }
390
          _blossom_set->eraseClass(blossom);
391
        }
392
      }
393
      _tree_set->eraseClass(tree);
394

	
395
    }
396

	
397
  public:
398

	
399
    /// \brief Constructor
400
    ///
401
    /// Constructor.
402
    MaxMatching(const Graph& graph)
403
      : _graph(graph), _matching(0), _status(0), _ear(0),
404
        _blossom_set_index(0), _blossom_set(0), _blossom_rep(0),
405
        _tree_set_index(0), _tree_set(0) {}
406

	
407
    ~MaxMatching() {
408
      destroyStructures();
409
    }
410

	
411
    /// \name Execution control
412
    /// The simplest way to execute the algorithm is to use the
413
    /// \c run() member function.
414
    /// \n
415

	
416
    /// If you need better control on the execution, you must call
417
    /// \ref init(), \ref greedyInit() or \ref matchingInit()
418
    /// functions first, then you can start the algorithm with the \ref
419
    /// startSparse() or startDense() functions.
420

	
421
    ///@{
422

	
423
    /// \brief Sets the actual matching to the empty matching.
424
    ///
425
    /// Sets the actual matching to the empty matching.
426
    ///
427
    void init() {
428
      createStructures();
429
      for(NodeIt n(_graph); n != INVALID; ++n) {
430
        (*_matching)[n] = INVALID;
431
        (*_status)[n] = UNMATCHED;
432
      }
433
    }
434

	
435
    ///\brief Finds an initial matching in a greedy way
436
    ///
437
    ///It finds an initial matching in a greedy way.
438
    void greedyInit() {
439
      createStructures();
440
      for (NodeIt n(_graph); n != INVALID; ++n) {
441
        (*_matching)[n] = INVALID;
442
        (*_status)[n] = UNMATCHED;
443
      }
444
      for (NodeIt n(_graph); n != INVALID; ++n) {
445
        if ((*_matching)[n] == INVALID) {
446
          for (OutArcIt a(_graph, n); a != INVALID ; ++a) {
447
            Node v = _graph.target(a);
448
            if ((*_matching)[v] == INVALID && v != n) {
449
              (*_matching)[n] = a;
450
              (*_status)[n] = MATCHED;
451
              (*_matching)[v] = _graph.oppositeArc(a);
452
              (*_status)[v] = MATCHED;
453
              break;
454
            }
455
          }
456
        }
457
      }
458
    }
459

	
460

	
461
    /// \brief Initialize the matching from a map containing.
462
    ///
463
    /// Initialize the matching from a \c bool valued \c Edge map. This
464
    /// map must have the property that there are no two incident edges
465
    /// with true value, ie. it contains a matching.
466
    /// \return \c true if the map contains a matching.
467
    template <typename MatchingMap>
468
    bool matchingInit(const MatchingMap& matching) {
469
      createStructures();
470

	
471
      for (NodeIt n(_graph); n != INVALID; ++n) {
472
        (*_matching)[n] = INVALID;
473
        (*_status)[n] = UNMATCHED;
474
      }
475
      for(EdgeIt e(_graph); e!=INVALID; ++e) {
476
        if (matching[e]) {
477

	
478
          Node u = _graph.u(e);
479
          if ((*_matching)[u] != INVALID) return false;
480
          (*_matching)[u] = _graph.direct(e, true);
481
          (*_status)[u] = MATCHED;
482

	
483
          Node v = _graph.v(e);
484
          if ((*_matching)[v] != INVALID) return false;
485
          (*_matching)[v] = _graph.direct(e, false);
486
          (*_status)[v] = MATCHED;
487
        }
488
      }
489
      return true;
490
    }
491

	
492
    /// \brief Starts Edmonds' algorithm
493
    ///
494
    /// If runs the original Edmonds' algorithm.
495
    void startSparse() {
496
      for(NodeIt n(_graph); n != INVALID; ++n) {
497
        if ((*_status)[n] == UNMATCHED) {
498
          (*_blossom_rep)[_blossom_set->insert(n)] = n;
499
          _tree_set->insert(n);
500
          (*_status)[n] = EVEN;
501
          processSparse(n);
502
        }
503
      }
504
    }
505

	
506
    /// \brief Starts Edmonds' algorithm.
507
    ///
508
    /// It runs Edmonds' algorithm with a heuristic of postponing
509
    /// shrinks, therefore resulting in a faster algorithm for dense graphs.
510
    void startDense() {
511
      for(NodeIt n(_graph); n != INVALID; ++n) {
512
        if ((*_status)[n] == UNMATCHED) {
513
          (*_blossom_rep)[_blossom_set->insert(n)] = n;
514
          _tree_set->insert(n);
515
          (*_status)[n] = EVEN;
516
          processDense(n);
517
        }
518
      }
519
    }
520

	
521

	
522
    /// \brief Runs Edmonds' algorithm
523
    ///
524
    /// Runs Edmonds' algorithm for sparse graphs (<tt>m<2*n</tt>)
525
    /// or Edmonds' algorithm with a heuristic of
526
    /// postponing shrinks for dense graphs.
527
    void run() {
528
      if (countEdges(_graph) < 2 * countNodes(_graph)) {
529
        greedyInit();
530
        startSparse();
531
      } else {
532
        init();
533
        startDense();
534
      }
535
    }
536

	
537
    /// @}
538

	
539
    /// \name Primal solution
540
    /// Functions to get the primal solution, ie. the matching.
541

	
542
    /// @{
543

	
544
    ///\brief Returns the size of the current matching.
545
    ///
546
    ///Returns the size of the current matching. After \ref
547
    ///run() it returns the size of the maximum matching in the graph.
548
    int matchingSize() const {
549
      int size = 0;
550
      for (NodeIt n(_graph); n != INVALID; ++n) {
551
        if ((*_matching)[n] != INVALID) {
552
          ++size;
553
        }
554
      }
555
      return size / 2;
556
    }
557

	
558
    /// \brief Returns true when the edge is in the matching.
559
    ///
560
    /// Returns true when the edge is in the matching.
561
    bool matching(const Edge& edge) const {
562
      return edge == (*_matching)[_graph.u(edge)];
563
    }
564

	
565
    /// \brief Returns the matching edge incident to the given node.
566
    ///
567
    /// Returns the matching edge of a \c node in the actual matching or
568
    /// INVALID if the \c node is not covered by the actual matching.
569
    Arc matching(const Node& n) const {
570
      return (*_matching)[n];
571
    }
572

	
573
    ///\brief Returns the mate of a node in the actual matching.
574
    ///
575
    ///Returns the mate of a \c node in the actual matching or
576
    ///INVALID if the \c node is not covered by the actual matching.
577
    Node mate(const Node& n) const {
578
      return (*_matching)[n] != INVALID ?
579
        _graph.target((*_matching)[n]) : INVALID;
580
    }
581

	
582
    /// @}
583

	
584
    /// \name Dual solution
585
    /// Functions to get the dual solution, ie. the decomposition.
586

	
587
    /// @{
588

	
589
    /// \brief Returns the class of the node in the Edmonds-Gallai
590
    /// decomposition.
591
    ///
592
    /// Returns the class of the node in the Edmonds-Gallai
593
    /// decomposition.
594
    Status decomposition(const Node& n) const {
595
      return (*_status)[n];
596
    }
597

	
598
    /// \brief Returns true when the node is in the barrier.
599
    ///
600
    /// Returns true when the node is in the barrier.
601
    bool barrier(const Node& n) const {
602
      return (*_status)[n] == ODD;
603
    }
604

	
605
    /// @}
606

	
607
  };
608

	
609
  /// \ingroup matching
610
  ///
611
  /// \brief Weighted matching in general graphs
612
  ///
613
  /// This class provides an efficient implementation of Edmond's
614
  /// maximum weighted matching algorithm. The implementation is based
615
  /// on extensive use of priority queues and provides
616
  /// \f$O(nm\log n)\f$ time complexity.
617
  ///
618
  /// The maximum weighted matching problem is to find undirected
619
  /// edges in the graph with maximum overall weight and no two of
620
  /// them shares their ends. The problem can be formulated with the
621
  /// following linear program.
622
  /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
623
  /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
624
      \quad \forall B\in\mathcal{O}\f] */
625
  /// \f[x_e \ge 0\quad \forall e\in E\f]
626
  /// \f[\max \sum_{e\in E}x_ew_e\f]
627
  /// where \f$\delta(X)\f$ is the set of edges incident to a node in
628
  /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
629
  /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
630
  /// subsets of the nodes.
631
  ///
632
  /// The algorithm calculates an optimal matching and a proof of the
633
  /// optimality. The solution of the dual problem can be used to check
634
  /// the result of the algorithm. The dual linear problem is the
635
  /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}
636
      z_B \ge w_{uv} \quad \forall uv\in E\f] */
637
  /// \f[y_u \ge 0 \quad \forall u \in V\f]
638
  /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
639
  /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
640
      \frac{\vert B \vert - 1}{2}z_B\f] */
641
  ///
642
  /// The algorithm can be executed with \c run() or the \c init() and
643
  /// then the \c start() member functions. After it the matching can
644
  /// be asked with \c matching() or mate() functions. The dual
645
  /// solution can be get with \c nodeValue(), \c blossomNum() and \c
646
  /// blossomValue() members and \ref MaxWeightedMatching::BlossomIt
647
  /// "BlossomIt" nested class, which is able to iterate on the nodes
648
  /// of a blossom. If the value type is integral then the dual
649
  /// solution is multiplied by \ref MaxWeightedMatching::dualScale "4".
650
  template <typename GR,
651
            typename WM = typename GR::template EdgeMap<int> >
652
  class MaxWeightedMatching {
653
  public:
654

	
655
    ///\e
656
    typedef GR Graph;
657
    ///\e
658
    typedef WM WeightMap;
659
    ///\e
660
    typedef typename WeightMap::Value Value;
661

	
662
    /// \brief Scaling factor for dual solution
663
    ///
664
    /// Scaling factor for dual solution, it is equal to 4 or 1
665
    /// according to the value type.
666
    static const int dualScale =
667
      std::numeric_limits<Value>::is_integer ? 4 : 1;
668

	
669
    typedef typename Graph::template NodeMap<typename Graph::Arc>
670
    MatchingMap;
671

	
672
  private:
673

	
674
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
675

	
676
    typedef typename Graph::template NodeMap<Value> NodePotential;
677
    typedef std::vector<Node> BlossomNodeList;
678

	
679
    struct BlossomVariable {
680
      int begin, end;
681
      Value value;
682

	
683
      BlossomVariable(int _begin, int _end, Value _value)
684
        : begin(_begin), end(_end), value(_value) {}
685

	
686
    };
687

	
688
    typedef std::vector<BlossomVariable> BlossomPotential;
689

	
690
    const Graph& _graph;
691
    const WeightMap& _weight;
692

	
693
    MatchingMap* _matching;
694

	
695
    NodePotential* _node_potential;
696

	
697
    BlossomPotential _blossom_potential;
698
    BlossomNodeList _blossom_node_list;
699

	
700
    int _node_num;
701
    int _blossom_num;
702

	
703
    typedef RangeMap<int> IntIntMap;
704

	
705
    enum Status {
706
      EVEN = -1, MATCHED = 0, ODD = 1, UNMATCHED = -2
707
    };
708

	
709
    typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
710
    struct BlossomData {
711
      int tree;
712
      Status status;
713
      Arc pred, next;
714
      Value pot, offset;
715
      Node base;
716
    };
717

	
718
    IntNodeMap *_blossom_index;
719
    BlossomSet *_blossom_set;
720
    RangeMap<BlossomData>* _blossom_data;
721

	
722
    IntNodeMap *_node_index;
723
    IntArcMap *_node_heap_index;
724

	
725
    struct NodeData {
726

	
727
      NodeData(IntArcMap& node_heap_index)
728
        : heap(node_heap_index) {}
729

	
730
      int blossom;
731
      Value pot;
732
      BinHeap<Value, IntArcMap> heap;
733
      std::map<int, Arc> heap_index;
734

	
735
      int tree;
736
    };
737

	
738
    RangeMap<NodeData>* _node_data;
739

	
740
    typedef ExtendFindEnum<IntIntMap> TreeSet;
741

	
742
    IntIntMap *_tree_set_index;
743
    TreeSet *_tree_set;
744

	
745
    IntNodeMap *_delta1_index;
746
    BinHeap<Value, IntNodeMap> *_delta1;
747

	
748
    IntIntMap *_delta2_index;
749
    BinHeap<Value, IntIntMap> *_delta2;
750

	
751
    IntEdgeMap *_delta3_index;
752
    BinHeap<Value, IntEdgeMap> *_delta3;
753

	
754
    IntIntMap *_delta4_index;
755
    BinHeap<Value, IntIntMap> *_delta4;
756

	
757
    Value _delta_sum;
758

	
759
    void createStructures() {
760
      _node_num = countNodes(_graph);
761
      _blossom_num = _node_num * 3 / 2;
762

	
763
      if (!_matching) {
764
        _matching = new MatchingMap(_graph);
765
      }
766
      if (!_node_potential) {
767
        _node_potential = new NodePotential(_graph);
768
      }
769
      if (!_blossom_set) {
770
        _blossom_index = new IntNodeMap(_graph);
771
        _blossom_set = new BlossomSet(*_blossom_index);
772
        _blossom_data = new RangeMap<BlossomData>(_blossom_num);
773
      }
774

	
775
      if (!_node_index) {
776
        _node_index = new IntNodeMap(_graph);
777
        _node_heap_index = new IntArcMap(_graph);
778
        _node_data = new RangeMap<NodeData>(_node_num,
779
                                              NodeData(*_node_heap_index));
780
      }
781

	
782
      if (!_tree_set) {
783
        _tree_set_index = new IntIntMap(_blossom_num);
784
        _tree_set = new TreeSet(*_tree_set_index);
785
      }
786
      if (!_delta1) {
787
        _delta1_index = new IntNodeMap(_graph);
788
        _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
789
      }
790
      if (!_delta2) {
791
        _delta2_index = new IntIntMap(_blossom_num);
792
        _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
793
      }
794
      if (!_delta3) {
795
        _delta3_index = new IntEdgeMap(_graph);
796
        _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
797
      }
798
      if (!_delta4) {
799
        _delta4_index = new IntIntMap(_blossom_num);
800
        _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
801
      }
802
    }
803

	
804
    void destroyStructures() {
805
      _node_num = countNodes(_graph);
806
      _blossom_num = _node_num * 3 / 2;
807

	
808
      if (_matching) {
809
        delete _matching;
810
      }
811
      if (_node_potential) {
812
        delete _node_potential;
813
      }
814
      if (_blossom_set) {
815
        delete _blossom_index;
816
        delete _blossom_set;
817
        delete _blossom_data;
818
      }
819

	
820
      if (_node_index) {
821
        delete _node_index;
822
        delete _node_heap_index;
823
        delete _node_data;
824
      }
825

	
826
      if (_tree_set) {
827
        delete _tree_set_index;
828
        delete _tree_set;
829
      }
830
      if (_delta1) {
831
        delete _delta1_index;
832
        delete _delta1;
833
      }
834
      if (_delta2) {
835
        delete _delta2_index;
836
        delete _delta2;
837
      }
838
      if (_delta3) {
839
        delete _delta3_index;
840
        delete _delta3;
841
      }
842
      if (_delta4) {
843
        delete _delta4_index;
844
        delete _delta4;
845
      }
846
    }
847

	
848
    void matchedToEven(int blossom, int tree) {
849
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
850
        _delta2->erase(blossom);
851
      }
852

	
853
      if (!_blossom_set->trivial(blossom)) {
854
        (*_blossom_data)[blossom].pot -=
855
          2 * (_delta_sum - (*_blossom_data)[blossom].offset);
856
      }
857

	
858
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
859
           n != INVALID; ++n) {
860

	
861
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
862
        int ni = (*_node_index)[n];
863

	
864
        (*_node_data)[ni].heap.clear();
865
        (*_node_data)[ni].heap_index.clear();
866

	
867
        (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
868

	
869
        _delta1->push(n, (*_node_data)[ni].pot);
870

	
871
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
872
          Node v = _graph.source(e);
873
          int vb = _blossom_set->find(v);
874
          int vi = (*_node_index)[v];
875

	
876
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
877
            dualScale * _weight[e];
878

	
879
          if ((*_blossom_data)[vb].status == EVEN) {
880
            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
881
              _delta3->push(e, rw / 2);
882
            }
883
          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
884
            if (_delta3->state(e) != _delta3->IN_HEAP) {
885
              _delta3->push(e, rw);
886
            }
887
          } else {
888
            typename std::map<int, Arc>::iterator it =
889
              (*_node_data)[vi].heap_index.find(tree);
890

	
891
            if (it != (*_node_data)[vi].heap_index.end()) {
892
              if ((*_node_data)[vi].heap[it->second] > rw) {
893
                (*_node_data)[vi].heap.replace(it->second, e);
894
                (*_node_data)[vi].heap.decrease(e, rw);
895
                it->second = e;
896
              }
897
            } else {
898
              (*_node_data)[vi].heap.push(e, rw);
899
              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
900
            }
901

	
902
            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
903
              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
904

	
905
              if ((*_blossom_data)[vb].status == MATCHED) {
906
                if (_delta2->state(vb) != _delta2->IN_HEAP) {
907
                  _delta2->push(vb, _blossom_set->classPrio(vb) -
908
                               (*_blossom_data)[vb].offset);
909
                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
910
                           (*_blossom_data)[vb].offset){
911
                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
912
                                   (*_blossom_data)[vb].offset);
913
                }
914
              }
915
            }
916
          }
917
        }
918
      }
919
      (*_blossom_data)[blossom].offset = 0;
920
    }
921

	
922
    void matchedToOdd(int blossom) {
923
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
924
        _delta2->erase(blossom);
925
      }
926
      (*_blossom_data)[blossom].offset += _delta_sum;
927
      if (!_blossom_set->trivial(blossom)) {
928
        _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
929
                     (*_blossom_data)[blossom].offset);
930
      }
931
    }
932

	
933
    void evenToMatched(int blossom, int tree) {
934
      if (!_blossom_set->trivial(blossom)) {
935
        (*_blossom_data)[blossom].pot += 2 * _delta_sum;
936
      }
937

	
938
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
939
           n != INVALID; ++n) {
940
        int ni = (*_node_index)[n];
941
        (*_node_data)[ni].pot -= _delta_sum;
942

	
943
        _delta1->erase(n);
944

	
945
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
946
          Node v = _graph.source(e);
947
          int vb = _blossom_set->find(v);
948
          int vi = (*_node_index)[v];
949

	
950
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
951
            dualScale * _weight[e];
952

	
953
          if (vb == blossom) {
954
            if (_delta3->state(e) == _delta3->IN_HEAP) {
955
              _delta3->erase(e);
956
            }
957
          } else if ((*_blossom_data)[vb].status == EVEN) {
958

	
959
            if (_delta3->state(e) == _delta3->IN_HEAP) {
960
              _delta3->erase(e);
961
            }
962

	
963
            int vt = _tree_set->find(vb);
964

	
965
            if (vt != tree) {
966

	
967
              Arc r = _graph.oppositeArc(e);
968

	
969
              typename std::map<int, Arc>::iterator it =
970
                (*_node_data)[ni].heap_index.find(vt);
971

	
972
              if (it != (*_node_data)[ni].heap_index.end()) {
973
                if ((*_node_data)[ni].heap[it->second] > rw) {
974
                  (*_node_data)[ni].heap.replace(it->second, r);
975
                  (*_node_data)[ni].heap.decrease(r, rw);
976
                  it->second = r;
977
                }
978
              } else {
979
                (*_node_data)[ni].heap.push(r, rw);
980
                (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
981
              }
982

	
983
              if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
984
                _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
985

	
986
                if (_delta2->state(blossom) != _delta2->IN_HEAP) {
987
                  _delta2->push(blossom, _blossom_set->classPrio(blossom) -
988
                               (*_blossom_data)[blossom].offset);
989
                } else if ((*_delta2)[blossom] >
990
                           _blossom_set->classPrio(blossom) -
991
                           (*_blossom_data)[blossom].offset){
992
                  _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
993
                                   (*_blossom_data)[blossom].offset);
994
                }
995
              }
996
            }
997

	
998
          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
999
            if (_delta3->state(e) == _delta3->IN_HEAP) {
1000
              _delta3->erase(e);
1001
            }
1002
          } else {
1003

	
1004
            typename std::map<int, Arc>::iterator it =
1005
              (*_node_data)[vi].heap_index.find(tree);
1006

	
1007
            if (it != (*_node_data)[vi].heap_index.end()) {
1008
              (*_node_data)[vi].heap.erase(it->second);
1009
              (*_node_data)[vi].heap_index.erase(it);
1010
              if ((*_node_data)[vi].heap.empty()) {
1011
                _blossom_set->increase(v, std::numeric_limits<Value>::max());
1012
              } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
1013
                _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
1014
              }
1015

	
1016
              if ((*_blossom_data)[vb].status == MATCHED) {
1017
                if (_blossom_set->classPrio(vb) ==
1018
                    std::numeric_limits<Value>::max()) {
1019
                  _delta2->erase(vb);
1020
                } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
1021
                           (*_blossom_data)[vb].offset) {
1022
                  _delta2->increase(vb, _blossom_set->classPrio(vb) -
1023
                                   (*_blossom_data)[vb].offset);
1024
                }
1025
              }
1026
            }
1027
          }
1028
        }
1029
      }
1030
    }
1031

	
1032
    void oddToMatched(int blossom) {
1033
      (*_blossom_data)[blossom].offset -= _delta_sum;
1034

	
1035
      if (_blossom_set->classPrio(blossom) !=
1036
          std::numeric_limits<Value>::max()) {
1037
        _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1038
                       (*_blossom_data)[blossom].offset);
1039
      }
1040

	
1041
      if (!_blossom_set->trivial(blossom)) {
1042
        _delta4->erase(blossom);
1043
      }
1044
    }
1045

	
1046
    void oddToEven(int blossom, int tree) {
1047
      if (!_blossom_set->trivial(blossom)) {
1048
        _delta4->erase(blossom);
1049
        (*_blossom_data)[blossom].pot -=
1050
          2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
1051
      }
1052

	
1053
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1054
           n != INVALID; ++n) {
1055
        int ni = (*_node_index)[n];
1056

	
1057
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
1058

	
1059
        (*_node_data)[ni].heap.clear();
1060
        (*_node_data)[ni].heap_index.clear();
1061
        (*_node_data)[ni].pot +=
1062
          2 * _delta_sum - (*_blossom_data)[blossom].offset;
1063

	
1064
        _delta1->push(n, (*_node_data)[ni].pot);
1065

	
1066
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
1067
          Node v = _graph.source(e);
1068
          int vb = _blossom_set->find(v);
1069
          int vi = (*_node_index)[v];
1070

	
1071
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1072
            dualScale * _weight[e];
1073

	
1074
          if ((*_blossom_data)[vb].status == EVEN) {
1075
            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
1076
              _delta3->push(e, rw / 2);
1077
            }
1078
          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
1079
            if (_delta3->state(e) != _delta3->IN_HEAP) {
1080
              _delta3->push(e, rw);
1081
            }
1082
          } else {
1083

	
1084
            typename std::map<int, Arc>::iterator it =
1085
              (*_node_data)[vi].heap_index.find(tree);
1086

	
1087
            if (it != (*_node_data)[vi].heap_index.end()) {
1088
              if ((*_node_data)[vi].heap[it->second] > rw) {
1089
                (*_node_data)[vi].heap.replace(it->second, e);
1090
                (*_node_data)[vi].heap.decrease(e, rw);
1091
                it->second = e;
1092
              }
1093
            } else {
1094
              (*_node_data)[vi].heap.push(e, rw);
1095
              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
1096
            }
1097

	
1098
            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
1099
              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
1100

	
1101
              if ((*_blossom_data)[vb].status == MATCHED) {
1102
                if (_delta2->state(vb) != _delta2->IN_HEAP) {
1103
                  _delta2->push(vb, _blossom_set->classPrio(vb) -
1104
                               (*_blossom_data)[vb].offset);
1105
                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
1106
                           (*_blossom_data)[vb].offset) {
1107
                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
1108
                                   (*_blossom_data)[vb].offset);
1109
                }
1110
              }
1111
            }
1112
          }
1113
        }
1114
      }
1115
      (*_blossom_data)[blossom].offset = 0;
1116
    }
1117

	
1118

	
1119
    void matchedToUnmatched(int blossom) {
1120
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1121
        _delta2->erase(blossom);
1122
      }
1123

	
1124
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1125
           n != INVALID; ++n) {
1126
        int ni = (*_node_index)[n];
1127

	
1128
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
1129

	
1130
        (*_node_data)[ni].heap.clear();
1131
        (*_node_data)[ni].heap_index.clear();
1132

	
1133
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1134
          Node v = _graph.target(e);
1135
          int vb = _blossom_set->find(v);
1136
          int vi = (*_node_index)[v];
1137

	
1138
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1139
            dualScale * _weight[e];
1140

	
1141
          if ((*_blossom_data)[vb].status == EVEN) {
1142
            if (_delta3->state(e) != _delta3->IN_HEAP) {
1143
              _delta3->push(e, rw);
1144
            }
1145
          }
1146
        }
1147
      }
1148
    }
1149

	
1150
    void unmatchedToMatched(int blossom) {
1151
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1152
           n != INVALID; ++n) {
1153
        int ni = (*_node_index)[n];
1154

	
1155
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
1156
          Node v = _graph.source(e);
1157
          int vb = _blossom_set->find(v);
1158
          int vi = (*_node_index)[v];
1159

	
1160
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1161
            dualScale * _weight[e];
1162

	
1163
          if (vb == blossom) {
1164
            if (_delta3->state(e) == _delta3->IN_HEAP) {
1165
              _delta3->erase(e);
1166
            }
1167
          } else if ((*_blossom_data)[vb].status == EVEN) {
1168

	
1169
            if (_delta3->state(e) == _delta3->IN_HEAP) {
1170
              _delta3->erase(e);
1171
            }
1172

	
1173
            int vt = _tree_set->find(vb);
1174

	
1175
            Arc r = _graph.oppositeArc(e);
1176

	
1177
            typename std::map<int, Arc>::iterator it =
1178
              (*_node_data)[ni].heap_index.find(vt);
1179

	
1180
            if (it != (*_node_data)[ni].heap_index.end()) {
1181
              if ((*_node_data)[ni].heap[it->second] > rw) {
1182
                (*_node_data)[ni].heap.replace(it->second, r);
1183
                (*_node_data)[ni].heap.decrease(r, rw);
1184
                it->second = r;
1185
              }
1186
            } else {
1187
              (*_node_data)[ni].heap.push(r, rw);
1188
              (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
1189
            }
1190

	
1191
            if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
1192
              _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
1193

	
1194
              if (_delta2->state(blossom) != _delta2->IN_HEAP) {
1195
                _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1196
                             (*_blossom_data)[blossom].offset);
1197
              } else if ((*_delta2)[blossom] > _blossom_set->classPrio(blossom)-
1198
                         (*_blossom_data)[blossom].offset){
1199
                _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
1200
                                 (*_blossom_data)[blossom].offset);
1201
              }
1202
            }
1203

	
1204
          } else if ((*_blossom_data)[vb].status == UNMATCHED) {
1205
            if (_delta3->state(e) == _delta3->IN_HEAP) {
1206
              _delta3->erase(e);
1207
            }
1208
          }
1209
        }
1210
      }
1211
    }
1212

	
1213
    void alternatePath(int even, int tree) {
1214
      int odd;
1215

	
1216
      evenToMatched(even, tree);
1217
      (*_blossom_data)[even].status = MATCHED;
1218

	
1219
      while ((*_blossom_data)[even].pred != INVALID) {
1220
        odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
1221
        (*_blossom_data)[odd].status = MATCHED;
1222
        oddToMatched(odd);
1223
        (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
1224

	
1225
        even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
1226
        (*_blossom_data)[even].status = MATCHED;
1227
        evenToMatched(even, tree);
1228
        (*_blossom_data)[even].next =
1229
          _graph.oppositeArc((*_blossom_data)[odd].pred);
1230
      }
1231

	
1232
    }
1233

	
1234
    void destroyTree(int tree) {
1235
      for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
1236
        if ((*_blossom_data)[b].status == EVEN) {
1237
          (*_blossom_data)[b].status = MATCHED;
1238
          evenToMatched(b, tree);
1239
        } else if ((*_blossom_data)[b].status == ODD) {
1240
          (*_blossom_data)[b].status = MATCHED;
1241
          oddToMatched(b);
1242
        }
1243
      }
1244
      _tree_set->eraseClass(tree);
1245
    }
1246

	
1247

	
1248
    void unmatchNode(const Node& node) {
1249
      int blossom = _blossom_set->find(node);
1250
      int tree = _tree_set->find(blossom);
1251

	
1252
      alternatePath(blossom, tree);
1253
      destroyTree(tree);
1254

	
1255
      (*_blossom_data)[blossom].status = UNMATCHED;
1256
      (*_blossom_data)[blossom].base = node;
1257
      matchedToUnmatched(blossom);
1258
    }
1259

	
1260

	
1261
    void augmentOnEdge(const Edge& edge) {
1262

	
1263
      int left = _blossom_set->find(_graph.u(edge));
1264
      int right = _blossom_set->find(_graph.v(edge));
1265

	
1266
      if ((*_blossom_data)[left].status == EVEN) {
1267
        int left_tree = _tree_set->find(left);
1268
        alternatePath(left, left_tree);
1269
        destroyTree(left_tree);
1270
      } else {
1271
        (*_blossom_data)[left].status = MATCHED;
1272
        unmatchedToMatched(left);
1273
      }
1274

	
1275
      if ((*_blossom_data)[right].status == EVEN) {
1276
        int right_tree = _tree_set->find(right);
1277
        alternatePath(right, right_tree);
1278
        destroyTree(right_tree);
1279
      } else {
1280
        (*_blossom_data)[right].status = MATCHED;
1281
        unmatchedToMatched(right);
1282
      }
1283

	
1284
      (*_blossom_data)[left].next = _graph.direct(edge, true);
1285
      (*_blossom_data)[right].next = _graph.direct(edge, false);
1286
    }
1287

	
1288
    void extendOnArc(const Arc& arc) {
1289
      int base = _blossom_set->find(_graph.target(arc));
1290
      int tree = _tree_set->find(base);
1291

	
1292
      int odd = _blossom_set->find(_graph.source(arc));
1293
      _tree_set->insert(odd, tree);
1294
      (*_blossom_data)[odd].status = ODD;
1295
      matchedToOdd(odd);
1296
      (*_blossom_data)[odd].pred = arc;
1297

	
1298
      int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
1299
      (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
1300
      _tree_set->insert(even, tree);
1301
      (*_blossom_data)[even].status = EVEN;
1302
      matchedToEven(even, tree);
1303
    }
1304

	
1305
    void shrinkOnEdge(const Edge& edge, int tree) {
1306
      int nca = -1;
1307
      std::vector<int> left_path, right_path;
1308

	
1309
      {
1310
        std::set<int> left_set, right_set;
1311
        int left = _blossom_set->find(_graph.u(edge));
1312
        left_path.push_back(left);
1313
        left_set.insert(left);
1314

	
1315
        int right = _blossom_set->find(_graph.v(edge));
1316
        right_path.push_back(right);
1317
        right_set.insert(right);
1318

	
1319
        while (true) {
1320

	
1321
          if ((*_blossom_data)[left].pred == INVALID) break;
1322

	
1323
          left =
1324
            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
1325
          left_path.push_back(left);
1326
          left =
1327
            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
1328
          left_path.push_back(left);
1329

	
1330
          left_set.insert(left);
1331

	
1332
          if (right_set.find(left) != right_set.end()) {
1333
            nca = left;
1334
            break;
1335
          }
1336

	
1337
          if ((*_blossom_data)[right].pred == INVALID) break;
1338

	
1339
          right =
1340
            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
1341
          right_path.push_back(right);
1342
          right =
1343
            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
1344
          right_path.push_back(right);
1345

	
1346
          right_set.insert(right);
1347

	
1348
          if (left_set.find(right) != left_set.end()) {
1349
            nca = right;
1350
            break;
1351
          }
1352

	
1353
        }
1354

	
1355
        if (nca == -1) {
1356
          if ((*_blossom_data)[left].pred == INVALID) {
1357
            nca = right;
1358
            while (left_set.find(nca) == left_set.end()) {
1359
              nca =
1360
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1361
              right_path.push_back(nca);
1362
              nca =
1363
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1364
              right_path.push_back(nca);
1365
            }
1366
          } else {
1367
            nca = left;
1368
            while (right_set.find(nca) == right_set.end()) {
1369
              nca =
1370
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1371
              left_path.push_back(nca);
1372
              nca =
1373
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1374
              left_path.push_back(nca);
1375
            }
1376
          }
1377
        }
1378
      }
1379

	
1380
      std::vector<int> subblossoms;
1381
      Arc prev;
1382

	
1383
      prev = _graph.direct(edge, true);
1384
      for (int i = 0; left_path[i] != nca; i += 2) {
1385
        subblossoms.push_back(left_path[i]);
1386
        (*_blossom_data)[left_path[i]].next = prev;
1387
        _tree_set->erase(left_path[i]);
1388

	
1389
        subblossoms.push_back(left_path[i + 1]);
1390
        (*_blossom_data)[left_path[i + 1]].status = EVEN;
1391
        oddToEven(left_path[i + 1], tree);
1392
        _tree_set->erase(left_path[i + 1]);
1393
        prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
1394
      }
1395

	
1396
      int k = 0;
1397
      while (right_path[k] != nca) ++k;
1398

	
1399
      subblossoms.push_back(nca);
1400
      (*_blossom_data)[nca].next = prev;
1401

	
1402
      for (int i = k - 2; i >= 0; i -= 2) {
1403
        subblossoms.push_back(right_path[i + 1]);
1404
        (*_blossom_data)[right_path[i + 1]].status = EVEN;
1405
        oddToEven(right_path[i + 1], tree);
1406
        _tree_set->erase(right_path[i + 1]);
1407

	
1408
        (*_blossom_data)[right_path[i + 1]].next =
1409
          (*_blossom_data)[right_path[i + 1]].pred;
1410

	
1411
        subblossoms.push_back(right_path[i]);
1412
        _tree_set->erase(right_path[i]);
1413
      }
1414

	
1415
      int surface =
1416
        _blossom_set->join(subblossoms.begin(), subblossoms.end());
1417

	
1418
      for (int i = 0; i < int(subblossoms.size()); ++i) {
1419
        if (!_blossom_set->trivial(subblossoms[i])) {
1420
          (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
1421
        }
1422
        (*_blossom_data)[subblossoms[i]].status = MATCHED;
1423
      }
1424

	
1425
      (*_blossom_data)[surface].pot = -2 * _delta_sum;
1426
      (*_blossom_data)[surface].offset = 0;
1427
      (*_blossom_data)[surface].status = EVEN;
1428
      (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
1429
      (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
1430

	
1431
      _tree_set->insert(surface, tree);
1432
      _tree_set->erase(nca);
1433
    }
1434

	
1435
    void splitBlossom(int blossom) {
1436
      Arc next = (*_blossom_data)[blossom].next;
1437
      Arc pred = (*_blossom_data)[blossom].pred;
1438

	
1439
      int tree = _tree_set->find(blossom);
1440

	
1441
      (*_blossom_data)[blossom].status = MATCHED;
1442
      oddToMatched(blossom);
1443
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1444
        _delta2->erase(blossom);
1445
      }
1446

	
1447
      std::vector<int> subblossoms;
1448
      _blossom_set->split(blossom, std::back_inserter(subblossoms));
1449

	
1450
      Value offset = (*_blossom_data)[blossom].offset;
1451
      int b = _blossom_set->find(_graph.source(pred));
1452
      int d = _blossom_set->find(_graph.source(next));
1453

	
1454
      int ib = -1, id = -1;
1455
      for (int i = 0; i < int(subblossoms.size()); ++i) {
1456
        if (subblossoms[i] == b) ib = i;
1457
        if (subblossoms[i] == d) id = i;
1458

	
1459
        (*_blossom_data)[subblossoms[i]].offset = offset;
1460
        if (!_blossom_set->trivial(subblossoms[i])) {
1461
          (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
1462
        }
1463
        if (_blossom_set->classPrio(subblossoms[i]) !=
1464
            std::numeric_limits<Value>::max()) {
1465
          _delta2->push(subblossoms[i],
1466
                        _blossom_set->classPrio(subblossoms[i]) -
1467
                        (*_blossom_data)[subblossoms[i]].offset);
1468
        }
1469
      }
1470

	
1471
      if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
1472
        for (int i = (id + 1) % subblossoms.size();
1473
             i != ib; i = (i + 2) % subblossoms.size()) {
1474
          int sb = subblossoms[i];
1475
          int tb = subblossoms[(i + 1) % subblossoms.size()];
1476
          (*_blossom_data)[sb].next =
1477
            _graph.oppositeArc((*_blossom_data)[tb].next);
1478
        }
1479

	
1480
        for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
1481
          int sb = subblossoms[i];
1482
          int tb = subblossoms[(i + 1) % subblossoms.size()];
1483
          int ub = subblossoms[(i + 2) % subblossoms.size()];
1484

	
1485
          (*_blossom_data)[sb].status = ODD;
1486
          matchedToOdd(sb);
1487
          _tree_set->insert(sb, tree);
1488
          (*_blossom_data)[sb].pred = pred;
1489
          (*_blossom_data)[sb].next =
1490
                           _graph.oppositeArc((*_blossom_data)[tb].next);
1491

	
1492
          pred = (*_blossom_data)[ub].next;
1493

	
1494
          (*_blossom_data)[tb].status = EVEN;
1495
          matchedToEven(tb, tree);
1496
          _tree_set->insert(tb, tree);
1497
          (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
1498
        }
1499

	
1500
        (*_blossom_data)[subblossoms[id]].status = ODD;
1501
        matchedToOdd(subblossoms[id]);
1502
        _tree_set->insert(subblossoms[id], tree);
1503
        (*_blossom_data)[subblossoms[id]].next = next;
1504
        (*_blossom_data)[subblossoms[id]].pred = pred;
1505

	
1506
      } else {
1507

	
1508
        for (int i = (ib + 1) % subblossoms.size();
1509
             i != id; i = (i + 2) % subblossoms.size()) {
1510
          int sb = subblossoms[i];
1511
          int tb = subblossoms[(i + 1) % subblossoms.size()];
1512
          (*_blossom_data)[sb].next =
1513
            _graph.oppositeArc((*_blossom_data)[tb].next);
1514
        }
1515

	
1516
        for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
1517
          int sb = subblossoms[i];
1518
          int tb = subblossoms[(i + 1) % subblossoms.size()];
1519
          int ub = subblossoms[(i + 2) % subblossoms.size()];
1520

	
1521
          (*_blossom_data)[sb].status = ODD;
1522
          matchedToOdd(sb);
1523
          _tree_set->insert(sb, tree);
1524
          (*_blossom_data)[sb].next = next;
1525
          (*_blossom_data)[sb].pred =
1526
            _graph.oppositeArc((*_blossom_data)[tb].next);
1527

	
1528
          (*_blossom_data)[tb].status = EVEN;
1529
          matchedToEven(tb, tree);
1530
          _tree_set->insert(tb, tree);
1531
          (*_blossom_data)[tb].pred =
1532
            (*_blossom_data)[tb].next =
1533
            _graph.oppositeArc((*_blossom_data)[ub].next);
1534
          next = (*_blossom_data)[ub].next;
1535
        }
1536

	
1537
        (*_blossom_data)[subblossoms[ib]].status = ODD;
1538
        matchedToOdd(subblossoms[ib]);
1539
        _tree_set->insert(subblossoms[ib], tree);
1540
        (*_blossom_data)[subblossoms[ib]].next = next;
1541
        (*_blossom_data)[subblossoms[ib]].pred = pred;
1542
      }
1543
      _tree_set->erase(blossom);
1544
    }
1545

	
1546
    void extractBlossom(int blossom, const Node& base, const Arc& matching) {
1547
      if (_blossom_set->trivial(blossom)) {
1548
        int bi = (*_node_index)[base];
1549
        Value pot = (*_node_data)[bi].pot;
1550

	
1551
        (*_matching)[base] = matching;
1552
        _blossom_node_list.push_back(base);
1553
        (*_node_potential)[base] = pot;
1554
      } else {
1555

	
1556
        Value pot = (*_blossom_data)[blossom].pot;
1557
        int bn = _blossom_node_list.size();
1558

	
1559
        std::vector<int> subblossoms;
1560
        _blossom_set->split(blossom, std::back_inserter(subblossoms));
1561
        int b = _blossom_set->find(base);
1562
        int ib = -1;
1563
        for (int i = 0; i < int(subblossoms.size()); ++i) {
1564
          if (subblossoms[i] == b) { ib = i; break; }
1565
        }
1566

	
1567
        for (int i = 1; i < int(subblossoms.size()); i += 2) {
1568
          int sb = subblossoms[(ib + i) % subblossoms.size()];
1569
          int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
1570

	
1571
          Arc m = (*_blossom_data)[tb].next;
1572
          extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
1573
          extractBlossom(tb, _graph.source(m), m);
1574
        }
1575
        extractBlossom(subblossoms[ib], base, matching);
1576

	
1577
        int en = _blossom_node_list.size();
1578

	
1579
        _blossom_potential.push_back(BlossomVariable(bn, en, pot));
1580
      }
1581
    }
1582

	
1583
    void extractMatching() {
1584
      std::vector<int> blossoms;
1585
      for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
1586
        blossoms.push_back(c);
1587
      }
1588

	
1589
      for (int i = 0; i < int(blossoms.size()); ++i) {
1590
        if ((*_blossom_data)[blossoms[i]].status == MATCHED) {
1591

	
1592
          Value offset = (*_blossom_data)[blossoms[i]].offset;
1593
          (*_blossom_data)[blossoms[i]].pot += 2 * offset;
1594
          for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
1595
               n != INVALID; ++n) {
1596
            (*_node_data)[(*_node_index)[n]].pot -= offset;
1597
          }
1598

	
1599
          Arc matching = (*_blossom_data)[blossoms[i]].next;
1600
          Node base = _graph.source(matching);
1601
          extractBlossom(blossoms[i], base, matching);
1602
        } else {
1603
          Node base = (*_blossom_data)[blossoms[i]].base;
1604
          extractBlossom(blossoms[i], base, INVALID);
1605
        }
1606
      }
1607
    }
1608

	
1609
  public:
1610

	
1611
    /// \brief Constructor
1612
    ///
1613
    /// Constructor.
1614
    MaxWeightedMatching(const Graph& graph, const WeightMap& weight)
1615
      : _graph(graph), _weight(weight), _matching(0),
1616
        _node_potential(0), _blossom_potential(), _blossom_node_list(),
1617
        _node_num(0), _blossom_num(0),
1618

	
1619
        _blossom_index(0), _blossom_set(0), _blossom_data(0),
1620
        _node_index(0), _node_heap_index(0), _node_data(0),
1621
        _tree_set_index(0), _tree_set(0),
1622

	
1623
        _delta1_index(0), _delta1(0),
1624
        _delta2_index(0), _delta2(0),
1625
        _delta3_index(0), _delta3(0),
1626
        _delta4_index(0), _delta4(0),
1627

	
1628
        _delta_sum() {}
1629

	
1630
    ~MaxWeightedMatching() {
1631
      destroyStructures();
1632
    }
1633

	
1634
    /// \name Execution control
1635
    /// The simplest way to execute the algorithm is to use the
1636
    /// \c run() member function.
1637

	
1638
    ///@{
1639

	
1640
    /// \brief Initialize the algorithm
1641
    ///
1642
    /// Initialize the algorithm
1643
    void init() {
1644
      createStructures();
1645

	
1646
      for (ArcIt e(_graph); e != INVALID; ++e) {
1647
        (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
1648
      }
1649
      for (NodeIt n(_graph); n != INVALID; ++n) {
1650
        (*_delta1_index)[n] = _delta1->PRE_HEAP;
1651
      }
1652
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1653
        (*_delta3_index)[e] = _delta3->PRE_HEAP;
1654
      }
1655
      for (int i = 0; i < _blossom_num; ++i) {
1656
        (*_delta2_index)[i] = _delta2->PRE_HEAP;
1657
        (*_delta4_index)[i] = _delta4->PRE_HEAP;
1658
      }
1659

	
1660
      int index = 0;
1661
      for (NodeIt n(_graph); n != INVALID; ++n) {
1662
        Value max = 0;
1663
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1664
          if (_graph.target(e) == n) continue;
1665
          if ((dualScale * _weight[e]) / 2 > max) {
1666
            max = (dualScale * _weight[e]) / 2;
1667
          }
1668
        }
1669
        (*_node_index)[n] = index;
1670
        (*_node_data)[index].pot = max;
1671
        _delta1->push(n, max);
1672
        int blossom =
1673
          _blossom_set->insert(n, std::numeric_limits<Value>::max());
1674

	
1675
        _tree_set->insert(blossom);
1676

	
1677
        (*_blossom_data)[blossom].status = EVEN;
1678
        (*_blossom_data)[blossom].pred = INVALID;
1679
        (*_blossom_data)[blossom].next = INVALID;
1680
        (*_blossom_data)[blossom].pot = 0;
1681
        (*_blossom_data)[blossom].offset = 0;
1682
        ++index;
1683
      }
1684
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1685
        int si = (*_node_index)[_graph.u(e)];
1686
        int ti = (*_node_index)[_graph.v(e)];
1687
        if (_graph.u(e) != _graph.v(e)) {
1688
          _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
1689
                            dualScale * _weight[e]) / 2);
1690
        }
1691
      }
1692
    }
1693

	
1694
    /// \brief Starts the algorithm
1695
    ///
1696
    /// Starts the algorithm
1697
    void start() {
1698
      enum OpType {
1699
        D1, D2, D3, D4
1700
      };
1701

	
1702
      int unmatched = _node_num;
1703
      while (unmatched > 0) {
1704
        Value d1 = !_delta1->empty() ?
1705
          _delta1->prio() : std::numeric_limits<Value>::max();
1706

	
1707
        Value d2 = !_delta2->empty() ?
1708
          _delta2->prio() : std::numeric_limits<Value>::max();
1709

	
1710
        Value d3 = !_delta3->empty() ?
1711
          _delta3->prio() : std::numeric_limits<Value>::max();
1712

	
1713
        Value d4 = !_delta4->empty() ?
1714
          _delta4->prio() : std::numeric_limits<Value>::max();
1715

	
1716
        _delta_sum = d1; OpType ot = D1;
1717
        if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1718
        if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
1719
        if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
1720

	
1721

	
1722
        switch (ot) {
1723
        case D1:
1724
          {
1725
            Node n = _delta1->top();
1726
            unmatchNode(n);
1727
            --unmatched;
1728
          }
1729
          break;
1730
        case D2:
1731
          {
1732
            int blossom = _delta2->top();
1733
            Node n = _blossom_set->classTop(blossom);
1734
            Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
1735
            extendOnArc(e);
1736
          }
1737
          break;
1738
        case D3:
1739
          {
1740
            Edge e = _delta3->top();
1741

	
1742
            int left_blossom = _blossom_set->find(_graph.u(e));
1743
            int right_blossom = _blossom_set->find(_graph.v(e));
1744

	
1745
            if (left_blossom == right_blossom) {
1746
              _delta3->pop();
1747
            } else {
1748
              int left_tree;
1749
              if ((*_blossom_data)[left_blossom].status == EVEN) {
1750
                left_tree = _tree_set->find(left_blossom);
1751
              } else {
1752
                left_tree = -1;
1753
                ++unmatched;
1754
              }
1755
              int right_tree;
1756
              if ((*_blossom_data)[right_blossom].status == EVEN) {
1757
                right_tree = _tree_set->find(right_blossom);
1758
              } else {
1759
                right_tree = -1;
1760
                ++unmatched;
1761
              }
1762

	
1763
              if (left_tree == right_tree) {
1764
                shrinkOnEdge(e, left_tree);
1765
              } else {
1766
                augmentOnEdge(e);
1767
                unmatched -= 2;
1768
              }
1769
            }
1770
          } break;
1771
        case D4:
1772
          splitBlossom(_delta4->top());
1773
          break;
1774
        }
1775
      }
1776
      extractMatching();
1777
    }
1778

	
1779
    /// \brief Runs %MaxWeightedMatching algorithm.
1780
    ///
1781
    /// This method runs the %MaxWeightedMatching algorithm.
1782
    ///
1783
    /// \note mwm.run() is just a shortcut of the following code.
1784
    /// \code
1785
    ///   mwm.init();
1786
    ///   mwm.start();
1787
    /// \endcode
1788
    void run() {
1789
      init();
1790
      start();
1791
    }
1792

	
1793
    /// @}
1794

	
1795
    /// \name Primal solution
1796
    /// Functions to get the primal solution, ie. the matching.
1797

	
1798
    /// @{
1799

	
1800
    /// \brief Returns the weight of the matching.
1801
    ///
1802
    /// Returns the weight of the matching.
1803
    Value matchingValue() const {
1804
      Value sum = 0;
1805
      for (NodeIt n(_graph); n != INVALID; ++n) {
1806
        if ((*_matching)[n] != INVALID) {
1807
          sum += _weight[(*_matching)[n]];
1808
        }
1809
      }
1810
      return sum /= 2;
1811
    }
1812

	
1813
    /// \brief Returns the cardinality of the matching.
1814
    ///
1815
    /// Returns the cardinality of the matching.
1816
    int matchingSize() const {
1817
      int num = 0;
1818
      for (NodeIt n(_graph); n != INVALID; ++n) {
1819
        if ((*_matching)[n] != INVALID) {
1820
          ++num;
1821
        }
1822
      }
1823
      return num /= 2;
1824
    }
1825

	
1826
    /// \brief Returns true when the edge is in the matching.
1827
    ///
1828
    /// Returns true when the edge is in the matching.
1829
    bool matching(const Edge& edge) const {
1830
      return edge == (*_matching)[_graph.u(edge)];
1831
    }
1832

	
1833
    /// \brief Returns the incident matching arc.
1834
    ///
1835
    /// Returns the incident matching arc from given node. If the
1836
    /// node is not matched then it gives back \c INVALID.
1837
    Arc matching(const Node& node) const {
1838
      return (*_matching)[node];
1839
    }
1840

	
1841
    /// \brief Returns the mate of the node.
1842
    ///
1843
    /// Returns the adjancent node in a mathcing arc. If the node is
1844
    /// not matched then it gives back \c INVALID.
1845
    Node mate(const Node& node) const {
1846
      return (*_matching)[node] != INVALID ?
1847
        _graph.target((*_matching)[node]) : INVALID;
1848
    }
1849

	
1850
    /// @}
1851

	
1852
    /// \name Dual solution
1853
    /// Functions to get the dual solution.
1854

	
1855
    /// @{
1856

	
1857
    /// \brief Returns the value of the dual solution.
1858
    ///
1859
    /// Returns the value of the dual solution. It should be equal to
1860
    /// the primal value scaled by \ref dualScale "dual scale".
1861
    Value dualValue() const {
1862
      Value sum = 0;
1863
      for (NodeIt n(_graph); n != INVALID; ++n) {
1864
        sum += nodeValue(n);
1865
      }
1866
      for (int i = 0; i < blossomNum(); ++i) {
1867
        sum += blossomValue(i) * (blossomSize(i) / 2);
1868
      }
1869
      return sum;
1870
    }
1871

	
1872
    /// \brief Returns the value of the node.
1873
    ///
1874
    /// Returns the the value of the node.
1875
    Value nodeValue(const Node& n) const {
1876
      return (*_node_potential)[n];
1877
    }
1878

	
1879
    /// \brief Returns the number of the blossoms in the basis.
1880
    ///
1881
    /// Returns the number of the blossoms in the basis.
1882
    /// \see BlossomIt
1883
    int blossomNum() const {
1884
      return _blossom_potential.size();
1885
    }
1886

	
1887

	
1888
    /// \brief Returns the number of the nodes in the blossom.
1889
    ///
1890
    /// Returns the number of the nodes in the blossom.
1891
    int blossomSize(int k) const {
1892
      return _blossom_potential[k].end - _blossom_potential[k].begin;
1893
    }
1894

	
1895
    /// \brief Returns the value of the blossom.
1896
    ///
1897
    /// Returns the the value of the blossom.
1898
    /// \see BlossomIt
1899
    Value blossomValue(int k) const {
1900
      return _blossom_potential[k].value;
1901
    }
1902

	
1903
    /// \brief Iterator for obtaining the nodes of the blossom.
1904
    ///
1905
    /// Iterator for obtaining the nodes of the blossom. This class
1906
    /// provides a common lemon style iterator for listing a
1907
    /// subset of the nodes.
1908
    class BlossomIt {
1909
    public:
1910

	
1911
      /// \brief Constructor.
1912
      ///
1913
      /// Constructor to get the nodes of the variable.
1914
      BlossomIt(const MaxWeightedMatching& algorithm, int variable)
1915
        : _algorithm(&algorithm)
1916
      {
1917
        _index = _algorithm->_blossom_potential[variable].begin;
1918
        _last = _algorithm->_blossom_potential[variable].end;
1919
      }
1920

	
1921
      /// \brief Conversion to node.
1922
      ///
1923
      /// Conversion to node.
1924
      operator Node() const {
1925
        return _algorithm->_blossom_node_list[_index];
1926
      }
1927

	
1928
      /// \brief Increment operator.
1929
      ///
1930
      /// Increment operator.
1931
      BlossomIt& operator++() {
1932
        ++_index;
1933
        return *this;
1934
      }
1935

	
1936
      /// \brief Validity checking
1937
      ///
1938
      /// Checks whether the iterator is invalid.
1939
      bool operator==(Invalid) const { return _index == _last; }
1940

	
1941
      /// \brief Validity checking
1942
      ///
1943
      /// Checks whether the iterator is valid.
1944
      bool operator!=(Invalid) const { return _index != _last; }
1945

	
1946
    private:
1947
      const MaxWeightedMatching* _algorithm;
1948
      int _last;
1949
      int _index;
1950
    };
1951

	
1952
    /// @}
1953

	
1954
  };
1955

	
1956
  /// \ingroup matching
1957
  ///
1958
  /// \brief Weighted perfect matching in general graphs
1959
  ///
1960
  /// This class provides an efficient implementation of Edmond's
1961
  /// maximum weighted perfect matching algorithm. The implementation
1962
  /// is based on extensive use of priority queues and provides
1963
  /// \f$O(nm\log n)\f$ time complexity.
1964
  ///
1965
  /// The maximum weighted matching problem is to find undirected
1966
  /// edges in the graph with maximum overall weight and no two of
1967
  /// them shares their ends and covers all nodes. The problem can be
1968
  /// formulated with the following linear program.
1969
  /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
1970
  /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
1971
      \quad \forall B\in\mathcal{O}\f] */
1972
  /// \f[x_e \ge 0\quad \forall e\in E\f]
1973
  /// \f[\max \sum_{e\in E}x_ew_e\f]
1974
  /// where \f$\delta(X)\f$ is the set of edges incident to a node in
1975
  /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
1976
  /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
1977
  /// subsets of the nodes.
1978
  ///
1979
  /// The algorithm calculates an optimal matching and a proof of the
1980
  /// optimality. The solution of the dual problem can be used to check
1981
  /// the result of the algorithm. The dual linear problem is the
1982
  /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge
1983
      w_{uv} \quad \forall uv\in E\f] */
1984
  /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
1985
  /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
1986
      \frac{\vert B \vert - 1}{2}z_B\f] */
1987
  ///
1988
  /// The algorithm can be executed with \c run() or the \c init() and
1989
  /// then the \c start() member functions. After it the matching can
1990
  /// be asked with \c matching() or mate() functions. The dual
1991
  /// solution can be get with \c nodeValue(), \c blossomNum() and \c
1992
  /// blossomValue() members and \ref MaxWeightedMatching::BlossomIt
1993
  /// "BlossomIt" nested class which is able to iterate on the nodes
1994
  /// of a blossom. If the value type is integral then the dual
1995
  /// solution is multiplied by \ref MaxWeightedMatching::dualScale "4".
1996
  template <typename GR,
1997
            typename WM = typename GR::template EdgeMap<int> >
1998
  class MaxWeightedPerfectMatching {
1999
  public:
2000

	
2001
    typedef GR Graph;
2002
    typedef WM WeightMap;
2003
    typedef typename WeightMap::Value Value;
2004

	
2005
    /// \brief Scaling factor for dual solution
2006
    ///
2007
    /// Scaling factor for dual solution, it is equal to 4 or 1
2008
    /// according to the value type.
2009
    static const int dualScale =
2010
      std::numeric_limits<Value>::is_integer ? 4 : 1;
2011

	
2012
    typedef typename Graph::template NodeMap<typename Graph::Arc>
2013
    MatchingMap;
2014

	
2015
  private:
2016

	
2017
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
2018

	
2019
    typedef typename Graph::template NodeMap<Value> NodePotential;
2020
    typedef std::vector<Node> BlossomNodeList;
2021

	
2022
    struct BlossomVariable {
2023
      int begin, end;
2024
      Value value;
2025

	
2026
      BlossomVariable(int _begin, int _end, Value _value)
2027
        : begin(_begin), end(_end), value(_value) {}
2028

	
2029
    };
2030

	
2031
    typedef std::vector<BlossomVariable> BlossomPotential;
2032

	
2033
    const Graph& _graph;
2034
    const WeightMap& _weight;
2035

	
2036
    MatchingMap* _matching;
2037

	
2038
    NodePotential* _node_potential;
2039

	
2040
    BlossomPotential _blossom_potential;
2041
    BlossomNodeList _blossom_node_list;
2042

	
2043
    int _node_num;
2044
    int _blossom_num;
2045

	
2046
    typedef RangeMap<int> IntIntMap;
2047

	
2048
    enum Status {
2049
      EVEN = -1, MATCHED = 0, ODD = 1
2050
    };
2051

	
2052
    typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
2053
    struct BlossomData {
2054
      int tree;
2055
      Status status;
2056
      Arc pred, next;
2057
      Value pot, offset;
2058
    };
2059

	
2060
    IntNodeMap *_blossom_index;
2061
    BlossomSet *_blossom_set;
2062
    RangeMap<BlossomData>* _blossom_data;
2063

	
2064
    IntNodeMap *_node_index;
2065
    IntArcMap *_node_heap_index;
2066

	
2067
    struct NodeData {
2068

	
2069
      NodeData(IntArcMap& node_heap_index)
2070
        : heap(node_heap_index) {}
2071

	
2072
      int blossom;
2073
      Value pot;
2074
      BinHeap<Value, IntArcMap> heap;
2075
      std::map<int, Arc> heap_index;
2076

	
2077
      int tree;
2078
    };
2079

	
2080
    RangeMap<NodeData>* _node_data;
2081

	
2082
    typedef ExtendFindEnum<IntIntMap> TreeSet;
2083

	
2084
    IntIntMap *_tree_set_index;
2085
    TreeSet *_tree_set;
2086

	
2087
    IntIntMap *_delta2_index;
2088
    BinHeap<Value, IntIntMap> *_delta2;
2089

	
2090
    IntEdgeMap *_delta3_index;
2091
    BinHeap<Value, IntEdgeMap> *_delta3;
2092

	
2093
    IntIntMap *_delta4_index;
2094
    BinHeap<Value, IntIntMap> *_delta4;
2095

	
2096
    Value _delta_sum;
2097

	
2098
    void createStructures() {
2099
      _node_num = countNodes(_graph);
2100
      _blossom_num = _node_num * 3 / 2;
2101

	
2102
      if (!_matching) {
2103
        _matching = new MatchingMap(_graph);
2104
      }
2105
      if (!_node_potential) {
2106
        _node_potential = new NodePotential(_graph);
2107
      }
2108
      if (!_blossom_set) {
2109
        _blossom_index = new IntNodeMap(_graph);
2110
        _blossom_set = new BlossomSet(*_blossom_index);
2111
        _blossom_data = new RangeMap<BlossomData>(_blossom_num);
2112
      }
2113

	
2114
      if (!_node_index) {
2115
        _node_index = new IntNodeMap(_graph);
2116
        _node_heap_index = new IntArcMap(_graph);
2117
        _node_data = new RangeMap<NodeData>(_node_num,
2118
                                            NodeData(*_node_heap_index));
2119
      }
2120

	
2121
      if (!_tree_set) {
2122
        _tree_set_index = new IntIntMap(_blossom_num);
2123
        _tree_set = new TreeSet(*_tree_set_index);
2124
      }
2125
      if (!_delta2) {
2126
        _delta2_index = new IntIntMap(_blossom_num);
2127
        _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
2128
      }
2129
      if (!_delta3) {
2130
        _delta3_index = new IntEdgeMap(_graph);
2131
        _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
2132
      }
2133
      if (!_delta4) {
2134
        _delta4_index = new IntIntMap(_blossom_num);
2135
        _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
2136
      }
2137
    }
2138

	
2139
    void destroyStructures() {
2140
      _node_num = countNodes(_graph);
2141
      _blossom_num = _node_num * 3 / 2;
2142

	
2143
      if (_matching) {
2144
        delete _matching;
2145
      }
2146
      if (_node_potential) {
2147
        delete _node_potential;
2148
      }
2149
      if (_blossom_set) {
2150
        delete _blossom_index;
2151
        delete _blossom_set;
2152
        delete _blossom_data;
2153
      }
2154

	
2155
      if (_node_index) {
2156
        delete _node_index;
2157
        delete _node_heap_index;
2158
        delete _node_data;
2159
      }
2160

	
2161
      if (_tree_set) {
2162
        delete _tree_set_index;
2163
        delete _tree_set;
2164
      }
2165
      if (_delta2) {
2166
        delete _delta2_index;
2167
        delete _delta2;
2168
      }
2169
      if (_delta3) {
2170
        delete _delta3_index;
2171
        delete _delta3;
2172
      }
2173
      if (_delta4) {
2174
        delete _delta4_index;
2175
        delete _delta4;
2176
      }
2177
    }
2178

	
2179
    void matchedToEven(int blossom, int tree) {
2180
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2181
        _delta2->erase(blossom);
2182
      }
2183

	
2184
      if (!_blossom_set->trivial(blossom)) {
2185
        (*_blossom_data)[blossom].pot -=
2186
          2 * (_delta_sum - (*_blossom_data)[blossom].offset);
2187
      }
2188

	
2189
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2190
           n != INVALID; ++n) {
2191

	
2192
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
2193
        int ni = (*_node_index)[n];
2194

	
2195
        (*_node_data)[ni].heap.clear();
2196
        (*_node_data)[ni].heap_index.clear();
2197

	
2198
        (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
2199

	
2200
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
2201
          Node v = _graph.source(e);
2202
          int vb = _blossom_set->find(v);
2203
          int vi = (*_node_index)[v];
2204

	
2205
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2206
            dualScale * _weight[e];
2207

	
2208
          if ((*_blossom_data)[vb].status == EVEN) {
2209
            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2210
              _delta3->push(e, rw / 2);
2211
            }
2212
          } else {
2213
            typename std::map<int, Arc>::iterator it =
2214
              (*_node_data)[vi].heap_index.find(tree);
2215

	
2216
            if (it != (*_node_data)[vi].heap_index.end()) {
2217
              if ((*_node_data)[vi].heap[it->second] > rw) {
2218
                (*_node_data)[vi].heap.replace(it->second, e);
2219
                (*_node_data)[vi].heap.decrease(e, rw);
2220
                it->second = e;
2221
              }
2222
            } else {
2223
              (*_node_data)[vi].heap.push(e, rw);
2224
              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2225
            }
2226

	
2227
            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2228
              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2229

	
2230
              if ((*_blossom_data)[vb].status == MATCHED) {
2231
                if (_delta2->state(vb) != _delta2->IN_HEAP) {
2232
                  _delta2->push(vb, _blossom_set->classPrio(vb) -
2233
                               (*_blossom_data)[vb].offset);
2234
                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2235
                           (*_blossom_data)[vb].offset){
2236
                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2237
                                   (*_blossom_data)[vb].offset);
2238
                }
2239
              }
2240
            }
2241
          }
2242
        }
2243
      }
2244
      (*_blossom_data)[blossom].offset = 0;
2245
    }
2246

	
2247
    void matchedToOdd(int blossom) {
2248
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2249
        _delta2->erase(blossom);
2250
      }
2251
      (*_blossom_data)[blossom].offset += _delta_sum;
2252
      if (!_blossom_set->trivial(blossom)) {
2253
        _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
2254
                     (*_blossom_data)[blossom].offset);
2255
      }
2256
    }
2257

	
2258
    void evenToMatched(int blossom, int tree) {
2259
      if (!_blossom_set->trivial(blossom)) {
2260
        (*_blossom_data)[blossom].pot += 2 * _delta_sum;
2261
      }
2262

	
2263
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2264
           n != INVALID; ++n) {
2265
        int ni = (*_node_index)[n];
2266
        (*_node_data)[ni].pot -= _delta_sum;
2267

	
2268
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
2269
          Node v = _graph.source(e);
2270
          int vb = _blossom_set->find(v);
2271
          int vi = (*_node_index)[v];
2272

	
2273
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2274
            dualScale * _weight[e];
2275

	
2276
          if (vb == blossom) {
2277
            if (_delta3->state(e) == _delta3->IN_HEAP) {
2278
              _delta3->erase(e);
2279
            }
2280
          } else if ((*_blossom_data)[vb].status == EVEN) {
2281

	
2282
            if (_delta3->state(e) == _delta3->IN_HEAP) {
2283
              _delta3->erase(e);
2284
            }
2285

	
2286
            int vt = _tree_set->find(vb);
2287

	
2288
            if (vt != tree) {
2289

	
2290
              Arc r = _graph.oppositeArc(e);
2291

	
2292
              typename std::map<int, Arc>::iterator it =
2293
                (*_node_data)[ni].heap_index.find(vt);
2294

	
2295
              if (it != (*_node_data)[ni].heap_index.end()) {
2296
                if ((*_node_data)[ni].heap[it->second] > rw) {
2297
                  (*_node_data)[ni].heap.replace(it->second, r);
2298
                  (*_node_data)[ni].heap.decrease(r, rw);
2299
                  it->second = r;
2300
                }
2301
              } else {
2302
                (*_node_data)[ni].heap.push(r, rw);
2303
                (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
2304
              }
2305

	
2306
              if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
2307
                _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
2308

	
2309
                if (_delta2->state(blossom) != _delta2->IN_HEAP) {
2310
                  _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2311
                               (*_blossom_data)[blossom].offset);
2312
                } else if ((*_delta2)[blossom] >
2313
                           _blossom_set->classPrio(blossom) -
2314
                           (*_blossom_data)[blossom].offset){
2315
                  _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
2316
                                   (*_blossom_data)[blossom].offset);
2317
                }
2318
              }
2319
            }
2320
          } else {
2321

	
2322
            typename std::map<int, Arc>::iterator it =
2323
              (*_node_data)[vi].heap_index.find(tree);
2324

	
2325
            if (it != (*_node_data)[vi].heap_index.end()) {
2326
              (*_node_data)[vi].heap.erase(it->second);
2327
              (*_node_data)[vi].heap_index.erase(it);
2328
              if ((*_node_data)[vi].heap.empty()) {
2329
                _blossom_set->increase(v, std::numeric_limits<Value>::max());
2330
              } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
2331
                _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
2332
              }
2333

	
2334
              if ((*_blossom_data)[vb].status == MATCHED) {
2335
                if (_blossom_set->classPrio(vb) ==
2336
                    std::numeric_limits<Value>::max()) {
2337
                  _delta2->erase(vb);
2338
                } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
2339
                           (*_blossom_data)[vb].offset) {
2340
                  _delta2->increase(vb, _blossom_set->classPrio(vb) -
2341
                                   (*_blossom_data)[vb].offset);
2342
                }
2343
              }
2344
            }
2345
          }
2346
        }
2347
      }
2348
    }
2349

	
2350
    void oddToMatched(int blossom) {
2351
      (*_blossom_data)[blossom].offset -= _delta_sum;
2352

	
2353
      if (_blossom_set->classPrio(blossom) !=
2354
          std::numeric_limits<Value>::max()) {
2355
        _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2356
                       (*_blossom_data)[blossom].offset);
2357
      }
2358

	
2359
      if (!_blossom_set->trivial(blossom)) {
2360
        _delta4->erase(blossom);
2361
      }
2362
    }
2363

	
2364
    void oddToEven(int blossom, int tree) {
2365
      if (!_blossom_set->trivial(blossom)) {
2366
        _delta4->erase(blossom);
2367
        (*_blossom_data)[blossom].pot -=
2368
          2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
2369
      }
2370

	
2371
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2372
           n != INVALID; ++n) {
2373
        int ni = (*_node_index)[n];
2374

	
2375
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
2376

	
2377
        (*_node_data)[ni].heap.clear();
2378
        (*_node_data)[ni].heap_index.clear();
2379
        (*_node_data)[ni].pot +=
2380
          2 * _delta_sum - (*_blossom_data)[blossom].offset;
2381

	
2382
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
2383
          Node v = _graph.source(e);
2384
          int vb = _blossom_set->find(v);
2385
          int vi = (*_node_index)[v];
2386

	
2387
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2388
            dualScale * _weight[e];
2389

	
2390
          if ((*_blossom_data)[vb].status == EVEN) {
2391
            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2392
              _delta3->push(e, rw / 2);
2393
            }
2394
          } else {
2395

	
2396
            typename std::map<int, Arc>::iterator it =
2397
              (*_node_data)[vi].heap_index.find(tree);
2398

	
2399
            if (it != (*_node_data)[vi].heap_index.end()) {
2400
              if ((*_node_data)[vi].heap[it->second] > rw) {
2401
                (*_node_data)[vi].heap.replace(it->second, e);
2402
                (*_node_data)[vi].heap.decrease(e, rw);
2403
                it->second = e;
2404
              }
2405
            } else {
2406
              (*_node_data)[vi].heap.push(e, rw);
2407
              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2408
            }
2409

	
2410
            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2411
              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2412

	
2413
              if ((*_blossom_data)[vb].status == MATCHED) {
2414
                if (_delta2->state(vb) != _delta2->IN_HEAP) {
2415
                  _delta2->push(vb, _blossom_set->classPrio(vb) -
2416
                               (*_blossom_data)[vb].offset);
2417
                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2418
                           (*_blossom_data)[vb].offset) {
2419
                  _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2420
                                   (*_blossom_data)[vb].offset);
2421
                }
2422
              }
2423
            }
2424
          }
2425
        }
2426
      }
2427
      (*_blossom_data)[blossom].offset = 0;
2428
    }
2429

	
2430
    void alternatePath(int even, int tree) {
2431
      int odd;
2432

	
2433
      evenToMatched(even, tree);
2434
      (*_blossom_data)[even].status = MATCHED;
2435

	
2436
      while ((*_blossom_data)[even].pred != INVALID) {
2437
        odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
2438
        (*_blossom_data)[odd].status = MATCHED;
2439
        oddToMatched(odd);
2440
        (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
2441

	
2442
        even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
2443
        (*_blossom_data)[even].status = MATCHED;
2444
        evenToMatched(even, tree);
2445
        (*_blossom_data)[even].next =
2446
          _graph.oppositeArc((*_blossom_data)[odd].pred);
2447
      }
2448

	
2449
    }
2450

	
2451
    void destroyTree(int tree) {
2452
      for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
2453
        if ((*_blossom_data)[b].status == EVEN) {
2454
          (*_blossom_data)[b].status = MATCHED;
2455
          evenToMatched(b, tree);
2456
        } else if ((*_blossom_data)[b].status == ODD) {
2457
          (*_blossom_data)[b].status = MATCHED;
2458
          oddToMatched(b);
2459
        }
2460
      }
2461
      _tree_set->eraseClass(tree);
2462
    }
2463

	
2464
    void augmentOnEdge(const Edge& edge) {
2465

	
2466
      int left = _blossom_set->find(_graph.u(edge));
2467
      int right = _blossom_set->find(_graph.v(edge));
2468

	
2469
      int left_tree = _tree_set->find(left);
2470
      alternatePath(left, left_tree);
2471
      destroyTree(left_tree);
2472

	
2473
      int right_tree = _tree_set->find(right);
2474
      alternatePath(right, right_tree);
2475
      destroyTree(right_tree);
2476

	
2477
      (*_blossom_data)[left].next = _graph.direct(edge, true);
2478
      (*_blossom_data)[right].next = _graph.direct(edge, false);
2479
    }
2480

	
2481
    void extendOnArc(const Arc& arc) {
2482
      int base = _blossom_set->find(_graph.target(arc));
2483
      int tree = _tree_set->find(base);
2484

	
2485
      int odd = _blossom_set->find(_graph.source(arc));
2486
      _tree_set->insert(odd, tree);
2487
      (*_blossom_data)[odd].status = ODD;
2488
      matchedToOdd(odd);
2489
      (*_blossom_data)[odd].pred = arc;
2490

	
2491
      int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
2492
      (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
2493
      _tree_set->insert(even, tree);
2494
      (*_blossom_data)[even].status = EVEN;
2495
      matchedToEven(even, tree);
2496
    }
2497

	
2498
    void shrinkOnEdge(const Edge& edge, int tree) {
2499
      int nca = -1;
2500
      std::vector<int> left_path, right_path;
2501

	
2502
      {
2503
        std::set<int> left_set, right_set;
2504
        int left = _blossom_set->find(_graph.u(edge));
2505
        left_path.push_back(left);
2506
        left_set.insert(left);
2507

	
2508
        int right = _blossom_set->find(_graph.v(edge));
2509
        right_path.push_back(right);
2510
        right_set.insert(right);
2511

	
2512
        while (true) {
2513

	
2514
          if ((*_blossom_data)[left].pred == INVALID) break;
2515

	
2516
          left =
2517
            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2518
          left_path.push_back(left);
2519
          left =
2520
            _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2521
          left_path.push_back(left);
2522

	
2523
          left_set.insert(left);
2524

	
2525
          if (right_set.find(left) != right_set.end()) {
2526
            nca = left;
2527
            break;
2528
          }
2529

	
2530
          if ((*_blossom_data)[right].pred == INVALID) break;
2531

	
2532
          right =
2533
            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2534
          right_path.push_back(right);
2535
          right =
2536
            _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2537
          right_path.push_back(right);
2538

	
2539
          right_set.insert(right);
2540

	
2541
          if (left_set.find(right) != left_set.end()) {
2542
            nca = right;
2543
            break;
2544
          }
2545

	
2546
        }
2547

	
2548
        if (nca == -1) {
2549
          if ((*_blossom_data)[left].pred == INVALID) {
2550
            nca = right;
2551
            while (left_set.find(nca) == left_set.end()) {
2552
              nca =
2553
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2554
              right_path.push_back(nca);
2555
              nca =
2556
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2557
              right_path.push_back(nca);
2558
            }
2559
          } else {
2560
            nca = left;
2561
            while (right_set.find(nca) == right_set.end()) {
2562
              nca =
2563
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2564
              left_path.push_back(nca);
2565
              nca =
2566
                _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2567
              left_path.push_back(nca);
2568
            }
2569
          }
2570
        }
2571
      }
2572

	
2573
      std::vector<int> subblossoms;
2574
      Arc prev;
2575

	
2576
      prev = _graph.direct(edge, true);
2577
      for (int i = 0; left_path[i] != nca; i += 2) {
2578
        subblossoms.push_back(left_path[i]);
2579
        (*_blossom_data)[left_path[i]].next = prev;
2580
        _tree_set->erase(left_path[i]);
2581

	
2582
        subblossoms.push_back(left_path[i + 1]);
2583
        (*_blossom_data)[left_path[i + 1]].status = EVEN;
2584
        oddToEven(left_path[i + 1], tree);
2585
        _tree_set->erase(left_path[i + 1]);
2586
        prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
2587
      }
2588

	
2589
      int k = 0;
2590
      while (right_path[k] != nca) ++k;
2591

	
2592
      subblossoms.push_back(nca);
2593
      (*_blossom_data)[nca].next = prev;
2594

	
2595
      for (int i = k - 2; i >= 0; i -= 2) {
2596
        subblossoms.push_back(right_path[i + 1]);
2597
        (*_blossom_data)[right_path[i + 1]].status = EVEN;
2598
        oddToEven(right_path[i + 1], tree);
2599
        _tree_set->erase(right_path[i + 1]);
2600

	
2601
        (*_blossom_data)[right_path[i + 1]].next =
2602
          (*_blossom_data)[right_path[i + 1]].pred;
2603

	
2604
        subblossoms.push_back(right_path[i]);
2605
        _tree_set->erase(right_path[i]);
2606
      }
2607

	
2608
      int surface =
2609
        _blossom_set->join(subblossoms.begin(), subblossoms.end());
2610

	
2611
      for (int i = 0; i < int(subblossoms.size()); ++i) {
2612
        if (!_blossom_set->trivial(subblossoms[i])) {
2613
          (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
2614
        }
2615
        (*_blossom_data)[subblossoms[i]].status = MATCHED;
2616
      }
2617

	
2618
      (*_blossom_data)[surface].pot = -2 * _delta_sum;
2619
      (*_blossom_data)[surface].offset = 0;
2620
      (*_blossom_data)[surface].status = EVEN;
2621
      (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
2622
      (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
2623

	
2624
      _tree_set->insert(surface, tree);
2625
      _tree_set->erase(nca);
2626
    }
2627

	
2628
    void splitBlossom(int blossom) {
2629
      Arc next = (*_blossom_data)[blossom].next;
2630
      Arc pred = (*_blossom_data)[blossom].pred;
2631

	
2632
      int tree = _tree_set->find(blossom);
2633

	
2634
      (*_blossom_data)[blossom].status = MATCHED;
2635
      oddToMatched(blossom);
2636
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2637
        _delta2->erase(blossom);
2638
      }
2639

	
2640
      std::vector<int> subblossoms;
2641
      _blossom_set->split(blossom, std::back_inserter(subblossoms));
2642

	
2643
      Value offset = (*_blossom_data)[blossom].offset;
2644
      int b = _blossom_set->find(_graph.source(pred));
2645
      int d = _blossom_set->find(_graph.source(next));
2646

	
2647
      int ib = -1, id = -1;
2648
      for (int i = 0; i < int(subblossoms.size()); ++i) {
2649
        if (subblossoms[i] == b) ib = i;
2650
        if (subblossoms[i] == d) id = i;
2651

	
2652
        (*_blossom_data)[subblossoms[i]].offset = offset;
2653
        if (!_blossom_set->trivial(subblossoms[i])) {
2654
          (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
2655
        }
2656
        if (_blossom_set->classPrio(subblossoms[i]) !=
2657
            std::numeric_limits<Value>::max()) {
2658
          _delta2->push(subblossoms[i],
2659
                        _blossom_set->classPrio(subblossoms[i]) -
2660
                        (*_blossom_data)[subblossoms[i]].offset);
2661
        }
2662
      }
2663

	
2664
      if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
2665
        for (int i = (id + 1) % subblossoms.size();
2666
             i != ib; i = (i + 2) % subblossoms.size()) {
2667
          int sb = subblossoms[i];
2668
          int tb = subblossoms[(i + 1) % subblossoms.size()];
2669
          (*_blossom_data)[sb].next =
2670
            _graph.oppositeArc((*_blossom_data)[tb].next);
2671
        }
2672

	
2673
        for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
2674
          int sb = subblossoms[i];
2675
          int tb = subblossoms[(i + 1) % subblossoms.size()];
2676
          int ub = subblossoms[(i + 2) % subblossoms.size()];
2677

	
2678
          (*_blossom_data)[sb].status = ODD;
2679
          matchedToOdd(sb);
2680
          _tree_set->insert(sb, tree);
2681
          (*_blossom_data)[sb].pred = pred;
2682
          (*_blossom_data)[sb].next =
2683
                           _graph.oppositeArc((*_blossom_data)[tb].next);
2684

	
2685
          pred = (*_blossom_data)[ub].next;
2686

	
2687
          (*_blossom_data)[tb].status = EVEN;
2688
          matchedToEven(tb, tree);
2689
          _tree_set->insert(tb, tree);
2690
          (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
2691
        }
2692

	
2693
        (*_blossom_data)[subblossoms[id]].status = ODD;
2694
        matchedToOdd(subblossoms[id]);
2695
        _tree_set->insert(subblossoms[id], tree);
2696
        (*_blossom_data)[subblossoms[id]].next = next;
2697
        (*_blossom_data)[subblossoms[id]].pred = pred;
2698

	
2699
      } else {
2700

	
2701
        for (int i = (ib + 1) % subblossoms.size();
2702
             i != id; i = (i + 2) % subblossoms.size()) {
2703
          int sb = subblossoms[i];
2704
          int tb = subblossoms[(i + 1) % subblossoms.size()];
2705
          (*_blossom_data)[sb].next =
2706
            _graph.oppositeArc((*_blossom_data)[tb].next);
2707
        }
2708

	
2709
        for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
2710
          int sb = subblossoms[i];
2711
          int tb = subblossoms[(i + 1) % subblossoms.size()];
2712
          int ub = subblossoms[(i + 2) % subblossoms.size()];
2713

	
2714
          (*_blossom_data)[sb].status = ODD;
2715
          matchedToOdd(sb);
2716
          _tree_set->insert(sb, tree);
2717
          (*_blossom_data)[sb].next = next;
2718
          (*_blossom_data)[sb].pred =
2719
            _graph.oppositeArc((*_blossom_data)[tb].next);
2720

	
2721
          (*_blossom_data)[tb].status = EVEN;
2722
          matchedToEven(tb, tree);
2723
          _tree_set->insert(tb, tree);
2724
          (*_blossom_data)[tb].pred =
2725
            (*_blossom_data)[tb].next =
2726
            _graph.oppositeArc((*_blossom_data)[ub].next);
2727
          next = (*_blossom_data)[ub].next;
2728
        }
2729

	
2730
        (*_blossom_data)[subblossoms[ib]].status = ODD;
2731
        matchedToOdd(subblossoms[ib]);
2732
        _tree_set->insert(subblossoms[ib], tree);
2733
        (*_blossom_data)[subblossoms[ib]].next = next;
2734
        (*_blossom_data)[subblossoms[ib]].pred = pred;
2735
      }
2736
      _tree_set->erase(blossom);
2737
    }
2738

	
2739
    void extractBlossom(int blossom, const Node& base, const Arc& matching) {
2740
      if (_blossom_set->trivial(blossom)) {
2741
        int bi = (*_node_index)[base];
2742
        Value pot = (*_node_data)[bi].pot;
2743

	
2744
        (*_matching)[base] = matching;
2745
        _blossom_node_list.push_back(base);
2746
        (*_node_potential)[base] = pot;
2747
      } else {
2748

	
2749
        Value pot = (*_blossom_data)[blossom].pot;
2750
        int bn = _blossom_node_list.size();
2751

	
2752
        std::vector<int> subblossoms;
2753
        _blossom_set->split(blossom, std::back_inserter(subblossoms));
2754
        int b = _blossom_set->find(base);
2755
        int ib = -1;
2756
        for (int i = 0; i < int(subblossoms.size()); ++i) {
2757
          if (subblossoms[i] == b) { ib = i; break; }
2758
        }
2759

	
2760
        for (int i = 1; i < int(subblossoms.size()); i += 2) {
2761
          int sb = subblossoms[(ib + i) % subblossoms.size()];
2762
          int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
2763

	
2764
          Arc m = (*_blossom_data)[tb].next;
2765
          extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
2766
          extractBlossom(tb, _graph.source(m), m);
2767
        }
2768
        extractBlossom(subblossoms[ib], base, matching);
2769

	
2770
        int en = _blossom_node_list.size();
2771

	
2772
        _blossom_potential.push_back(BlossomVariable(bn, en, pot));
2773
      }
2774
    }
2775

	
2776
    void extractMatching() {
2777
      std::vector<int> blossoms;
2778
      for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
2779
        blossoms.push_back(c);
2780
      }
2781

	
2782
      for (int i = 0; i < int(blossoms.size()); ++i) {
2783

	
2784
        Value offset = (*_blossom_data)[blossoms[i]].offset;
2785
        (*_blossom_data)[blossoms[i]].pot += 2 * offset;
2786
        for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
2787
             n != INVALID; ++n) {
2788
          (*_node_data)[(*_node_index)[n]].pot -= offset;
2789
        }
2790

	
2791
        Arc matching = (*_blossom_data)[blossoms[i]].next;
2792
        Node base = _graph.source(matching);
2793
        extractBlossom(blossoms[i], base, matching);
2794
      }
2795
    }
2796

	
2797
  public:
2798

	
2799
    /// \brief Constructor
2800
    ///
2801
    /// Constructor.
2802
    MaxWeightedPerfectMatching(const Graph& graph, const WeightMap& weight)
2803
      : _graph(graph), _weight(weight), _matching(0),
2804
        _node_potential(0), _blossom_potential(), _blossom_node_list(),
2805
        _node_num(0), _blossom_num(0),
2806

	
2807
        _blossom_index(0), _blossom_set(0), _blossom_data(0),
2808
        _node_index(0), _node_heap_index(0), _node_data(0),
2809
        _tree_set_index(0), _tree_set(0),
2810

	
2811
        _delta2_index(0), _delta2(0),
2812
        _delta3_index(0), _delta3(0),
2813
        _delta4_index(0), _delta4(0),
2814

	
2815
        _delta_sum() {}
2816

	
2817
    ~MaxWeightedPerfectMatching() {
2818
      destroyStructures();
2819
    }
2820

	
2821
    /// \name Execution control
2822
    /// The simplest way to execute the algorithm is to use the
2823
    /// \c run() member function.
2824

	
2825
    ///@{
2826

	
2827
    /// \brief Initialize the algorithm
2828
    ///
2829
    /// Initialize the algorithm
2830
    void init() {
2831
      createStructures();
2832

	
2833
      for (ArcIt e(_graph); e != INVALID; ++e) {
2834
        (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
2835
      }
2836
      for (EdgeIt e(_graph); e != INVALID; ++e) {
2837
        (*_delta3_index)[e] = _delta3->PRE_HEAP;
2838
      }
2839
      for (int i = 0; i < _blossom_num; ++i) {
2840
        (*_delta2_index)[i] = _delta2->PRE_HEAP;
2841
        (*_delta4_index)[i] = _delta4->PRE_HEAP;
2842
      }
2843

	
2844
      int index = 0;
2845
      for (NodeIt n(_graph); n != INVALID; ++n) {
2846
        Value max = - std::numeric_limits<Value>::max();
2847
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
2848
          if (_graph.target(e) == n) continue;
2849
          if ((dualScale * _weight[e]) / 2 > max) {
2850
            max = (dualScale * _weight[e]) / 2;
2851
          }
2852
        }
2853
        (*_node_index)[n] = index;
2854
        (*_node_data)[index].pot = max;
2855
        int blossom =
2856
          _blossom_set->insert(n, std::numeric_limits<Value>::max());
2857

	
2858
        _tree_set->insert(blossom);
2859

	
2860
        (*_blossom_data)[blossom].status = EVEN;
2861
        (*_blossom_data)[blossom].pred = INVALID;
2862
        (*_blossom_data)[blossom].next = INVALID;
2863
        (*_blossom_data)[blossom].pot = 0;
2864
        (*_blossom_data)[blossom].offset = 0;
2865
        ++index;
2866
      }
2867
      for (EdgeIt e(_graph); e != INVALID; ++e) {
2868
        int si = (*_node_index)[_graph.u(e)];
2869
        int ti = (*_node_index)[_graph.v(e)];
2870
        if (_graph.u(e) != _graph.v(e)) {
2871
          _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
2872
                            dualScale * _weight[e]) / 2);
2873
        }
2874
      }
2875
    }
2876

	
2877
    /// \brief Starts the algorithm
2878
    ///
2879
    /// Starts the algorithm
2880
    bool start() {
2881
      enum OpType {
2882
        D2, D3, D4
2883
      };
2884

	
2885
      int unmatched = _node_num;
2886
      while (unmatched > 0) {
2887
        Value d2 = !_delta2->empty() ?
2888
          _delta2->prio() : std::numeric_limits<Value>::max();
2889

	
2890
        Value d3 = !_delta3->empty() ?
2891
          _delta3->prio() : std::numeric_limits<Value>::max();
2892

	
2893
        Value d4 = !_delta4->empty() ?
2894
          _delta4->prio() : std::numeric_limits<Value>::max();
2895

	
2896
        _delta_sum = d2; OpType ot = D2;
2897
        if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
2898
        if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
2899

	
2900
        if (_delta_sum == std::numeric_limits<Value>::max()) {
2901
          return false;
2902
        }
2903

	
2904
        switch (ot) {
2905
        case D2:
2906
          {
2907
            int blossom = _delta2->top();
2908
            Node n = _blossom_set->classTop(blossom);
2909
            Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
2910
            extendOnArc(e);
2911
          }
2912
          break;
2913
        case D3:
2914
          {
2915
            Edge e = _delta3->top();
2916

	
2917
            int left_blossom = _blossom_set->find(_graph.u(e));
2918
            int right_blossom = _blossom_set->find(_graph.v(e));
2919

	
2920
            if (left_blossom == right_blossom) {
2921
              _delta3->pop();
2922
            } else {
2923
              int left_tree = _tree_set->find(left_blossom);
2924
              int right_tree = _tree_set->find(right_blossom);
2925

	
2926
              if (left_tree == right_tree) {
2927
                shrinkOnEdge(e, left_tree);
2928
              } else {
2929
                augmentOnEdge(e);
2930
                unmatched -= 2;
2931
              }
2932
            }
2933
          } break;
2934
        case D4:
2935
          splitBlossom(_delta4->top());
2936
          break;
2937
        }
2938
      }
2939
      extractMatching();
2940
      return true;
2941
    }
2942

	
2943
    /// \brief Runs %MaxWeightedPerfectMatching algorithm.
2944
    ///
2945
    /// This method runs the %MaxWeightedPerfectMatching algorithm.
2946
    ///
2947
    /// \note mwm.run() is just a shortcut of the following code.
2948
    /// \code
2949
    ///   mwm.init();
2950
    ///   mwm.start();
2951
    /// \endcode
2952
    bool run() {
2953
      init();
2954
      return start();
2955
    }
2956

	
2957
    /// @}
2958

	
2959
    /// \name Primal solution
2960
    /// Functions to get the primal solution, ie. the matching.
2961

	
2962
    /// @{
2963

	
2964
    /// \brief Returns the matching value.
2965
    ///
2966
    /// Returns the matching value.
2967
    Value matchingValue() const {
2968
      Value sum = 0;
2969
      for (NodeIt n(_graph); n != INVALID; ++n) {
2970
        if ((*_matching)[n] != INVALID) {
2971
          sum += _weight[(*_matching)[n]];
2972
        }
2973
      }
2974
      return sum /= 2;
2975
    }
2976

	
2977
    /// \brief Returns true when the edge is in the matching.
2978
    ///
2979
    /// Returns true when the edge is in the matching.
2980
    bool matching(const Edge& edge) const {
2981
      return static_cast<const Edge&>((*_matching)[_graph.u(edge)]) == edge;
2982
    }
2983

	
2984
    /// \brief Returns the incident matching edge.
2985
    ///
2986
    /// Returns the incident matching arc from given edge.
2987
    Arc matching(const Node& node) const {
2988
      return (*_matching)[node];
2989
    }
2990

	
2991
    /// \brief Returns the mate of the node.
2992
    ///
2993
    /// Returns the adjancent node in a mathcing arc.
2994
    Node mate(const Node& node) const {
2995
      return _graph.target((*_matching)[node]);
2996
    }
2997

	
2998
    /// @}
2999

	
3000
    /// \name Dual solution
3001
    /// Functions to get the dual solution.
3002

	
3003
    /// @{
3004

	
3005
    /// \brief Returns the value of the dual solution.
3006
    ///
3007
    /// Returns the value of the dual solution. It should be equal to
3008
    /// the primal value scaled by \ref dualScale "dual scale".
3009
    Value dualValue() const {
3010
      Value sum = 0;
3011
      for (NodeIt n(_graph); n != INVALID; ++n) {
3012
        sum += nodeValue(n);
3013
      }
3014
      for (int i = 0; i < blossomNum(); ++i) {
3015
        sum += blossomValue(i) * (blossomSize(i) / 2);
3016
      }
3017
      return sum;
3018
    }
3019

	
3020
    /// \brief Returns the value of the node.
3021
    ///
3022
    /// Returns the the value of the node.
3023
    Value nodeValue(const Node& n) const {
3024
      return (*_node_potential)[n];
3025
    }
3026

	
3027
    /// \brief Returns the number of the blossoms in the basis.
3028
    ///
3029
    /// Returns the number of the blossoms in the basis.
3030
    /// \see BlossomIt
3031
    int blossomNum() const {
3032
      return _blossom_potential.size();
3033
    }
3034

	
3035

	
3036
    /// \brief Returns the number of the nodes in the blossom.
3037
    ///
3038
    /// Returns the number of the nodes in the blossom.
3039
    int blossomSize(int k) const {
3040
      return _blossom_potential[k].end - _blossom_potential[k].begin;
3041
    }
3042

	
3043
    /// \brief Returns the value of the blossom.
3044
    ///
3045
    /// Returns the the value of the blossom.
3046
    /// \see BlossomIt
3047
    Value blossomValue(int k) const {
3048
      return _blossom_potential[k].value;
3049
    }
3050

	
3051
    /// \brief Iterator for obtaining the nodes of the blossom.
3052
    ///
3053
    /// Iterator for obtaining the nodes of the blossom. This class
3054
    /// provides a common lemon style iterator for listing a
3055
    /// subset of the nodes.
3056
    class BlossomIt {
3057
    public:
3058

	
3059
      /// \brief Constructor.
3060
      ///
3061
      /// Constructor to get the nodes of the variable.
3062
      BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable)
3063
        : _algorithm(&algorithm)
3064
      {
3065
        _index = _algorithm->_blossom_potential[variable].begin;
3066
        _last = _algorithm->_blossom_potential[variable].end;
3067
      }
3068

	
3069
      /// \brief Conversion to node.
3070
      ///
3071
      /// Conversion to node.
3072
      operator Node() const {
3073
        return _algorithm->_blossom_node_list[_index];
3074
      }
3075

	
3076
      /// \brief Increment operator.
3077
      ///
3078
      /// Increment operator.
3079
      BlossomIt& operator++() {
3080
        ++_index;
3081
        return *this;
3082
      }
3083

	
3084
      /// \brief Validity checking
3085
      ///
3086
      /// Checks whether the iterator is invalid.
3087
      bool operator==(Invalid) const { return _index == _last; }
3088

	
3089
      /// \brief Validity checking
3090
      ///
3091
      /// Checks whether the iterator is valid.
3092
      bool operator!=(Invalid) const { return _index != _last; }
3093

	
3094
    private:
3095
      const MaxWeightedPerfectMatching* _algorithm;
3096
      int _last;
3097
      int _index;
3098
    };
3099

	
3100
    /// @}
3101

	
3102
  };
3103

	
3104

	
3105
} //END OF NAMESPACE LEMON
3106

	
3107
#endif //LEMON_MAX_MATCHING_H
Ignore white space 6 line context
1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library.
4
 *
5
 * Copyright (C) 2003-2009
6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8
 *
9
 * Permission to use, modify and distribute this software is granted
10
 * provided that this copyright notice appears in all copies. For
11
 * precise terms see the accompanying LICENSE file.
12
 *
13
 * This software is provided "AS IS" with no warranty of any kind,
14
 * express or implied, and with no claim as to its suitability for any
15
 * purpose.
16
 *
17
 */
18

	
19
#include <iostream>
20
#include <sstream>
21
#include <vector>
22
#include <queue>
23
#include <lemon/math.h>
24
#include <cstdlib>
25

	
26
#include <lemon/max_matching.h>
27
#include <lemon/smart_graph.h>
28
#include <lemon/lgf_reader.h>
29

	
30
#include "test_tools.h"
31

	
32
using namespace std;
33
using namespace lemon;
34

	
35
GRAPH_TYPEDEFS(SmartGraph);
36

	
37

	
38
const int lgfn = 3;
39
const std::string lgf[lgfn] = {
40
  "@nodes\n"
41
  "label\n"
42
  "0\n"
43
  "1\n"
44
  "2\n"
45
  "3\n"
46
  "4\n"
47
  "5\n"
48
  "6\n"
49
  "7\n"
50
  "@edges\n"
51
  "     label  weight\n"
52
  "7 4  0      984\n"
53
  "0 7  1      73\n"
54
  "7 1  2      204\n"
55
  "2 3  3      583\n"
56
  "2 7  4      565\n"
57
  "2 1  5      582\n"
58
  "0 4  6      551\n"
59
  "2 5  7      385\n"
60
  "1 5  8      561\n"
61
  "5 3  9      484\n"
62
  "7 5  10     904\n"
63
  "3 6  11     47\n"
64
  "7 6  12     888\n"
65
  "3 0  13     747\n"
66
  "6 1  14     310\n",
67

	
68
  "@nodes\n"
69
  "label\n"
70
  "0\n"
71
  "1\n"
72
  "2\n"
73
  "3\n"
74
  "4\n"
75
  "5\n"
76
  "6\n"
77
  "7\n"
78
  "@edges\n"
79
  "     label  weight\n"
80
  "2 5  0      710\n"
81
  "0 5  1      241\n"
82
  "2 4  2      856\n"
83
  "2 6  3      762\n"
84
  "4 1  4      747\n"
85
  "6 1  5      962\n"
86
  "4 7  6      723\n"
87
  "1 7  7      661\n"
88
  "2 3  8      376\n"
89
  "1 0  9      416\n"
90
  "6 7  10     391\n",
91

	
92
  "@nodes\n"
93
  "label\n"
94
  "0\n"
95
  "1\n"
96
  "2\n"
97
  "3\n"
98
  "4\n"
99
  "5\n"
100
  "6\n"
101
  "7\n"
102
  "@edges\n"
103
  "     label  weight\n"
104
  "6 2  0      553\n"
105
  "0 7  1      653\n"
106
  "6 3  2      22\n"
107
  "4 7  3      846\n"
108
  "7 2  4      981\n"
109
  "7 6  5      250\n"
110
  "5 2  6      539\n",
111
};
112

	
113
void checkMatching(const SmartGraph& graph,
114
                   const MaxMatching<SmartGraph>& mm) {
115
  int num = 0;
116

	
117
  IntNodeMap comp_index(graph);
118
  UnionFind<IntNodeMap> comp(comp_index);
119

	
120
  int barrier_num = 0;
121

	
122
  for (NodeIt n(graph); n != INVALID; ++n) {
123
    check(mm.decomposition(n) == MaxMatching<SmartGraph>::EVEN ||
124
          mm.matching(n) != INVALID, "Wrong Gallai-Edmonds decomposition");
125
    if (mm.decomposition(n) == MaxMatching<SmartGraph>::ODD) {
126
      ++barrier_num;
127
    } else {
128
      comp.insert(n);
129
    }
130
  }
131

	
132
  for (EdgeIt e(graph); e != INVALID; ++e) {
133
    if (mm.matching(e)) {
134
      check(e == mm.matching(graph.u(e)), "Wrong matching");
135
      check(e == mm.matching(graph.v(e)), "Wrong matching");
136
      ++num;
137
    }
138
    check(mm.decomposition(graph.u(e)) != MaxMatching<SmartGraph>::EVEN ||
139
          mm.decomposition(graph.v(e)) != MaxMatching<SmartGraph>::MATCHED,
140
          "Wrong Gallai-Edmonds decomposition");
141

	
142
    check(mm.decomposition(graph.v(e)) != MaxMatching<SmartGraph>::EVEN ||
143
          mm.decomposition(graph.u(e)) != MaxMatching<SmartGraph>::MATCHED,
144
          "Wrong Gallai-Edmonds decomposition");
145

	
146
    if (mm.decomposition(graph.u(e)) != MaxMatching<SmartGraph>::ODD &&
147
        mm.decomposition(graph.v(e)) != MaxMatching<SmartGraph>::ODD) {
148
      comp.join(graph.u(e), graph.v(e));
149
    }
150
  }
151

	
152
  std::set<int> comp_root;
153
  int odd_comp_num = 0;
154
  for (NodeIt n(graph); n != INVALID; ++n) {
155
    if (mm.decomposition(n) != MaxMatching<SmartGraph>::ODD) {
156
      int root = comp.find(n);
157
      if (comp_root.find(root) == comp_root.end()) {
158
        comp_root.insert(root);
159
        if (comp.size(n) % 2 == 1) {
160
          ++odd_comp_num;
161
        }
162
      }
163
    }
164
  }
165

	
166
  check(mm.matchingSize() == num, "Wrong matching");
167
  check(2 * num == countNodes(graph) - (odd_comp_num - barrier_num),
168
         "Wrong matching");
169
  return;
170
}
171

	
172
void checkWeightedMatching(const SmartGraph& graph,
173
                   const SmartGraph::EdgeMap<int>& weight,
174
                   const MaxWeightedMatching<SmartGraph>& mwm) {
175
  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
176
    if (graph.u(e) == graph.v(e)) continue;
177
    int rw = mwm.nodeValue(graph.u(e)) + mwm.nodeValue(graph.v(e));
178

	
179
    for (int i = 0; i < mwm.blossomNum(); ++i) {
180
      bool s = false, t = false;
181
      for (MaxWeightedMatching<SmartGraph>::BlossomIt n(mwm, i);
182
           n != INVALID; ++n) {
183
        if (graph.u(e) == n) s = true;
184
        if (graph.v(e) == n) t = true;
185
      }
186
      if (s == true && t == true) {
187
        rw += mwm.blossomValue(i);
188
      }
189
    }
190
    rw -= weight[e] * mwm.dualScale;
191

	
192
    check(rw >= 0, "Negative reduced weight");
193
    check(rw == 0 || !mwm.matching(e),
194
          "Non-zero reduced weight on matching edge");
195
  }
196

	
197
  int pv = 0;
198
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
199
    if (mwm.matching(n) != INVALID) {
200
      check(mwm.nodeValue(n) >= 0, "Invalid node value");
201
      pv += weight[mwm.matching(n)];
202
      SmartGraph::Node o = graph.target(mwm.matching(n));
203
      check(mwm.mate(n) == o, "Invalid matching");
204
      check(mwm.matching(n) == graph.oppositeArc(mwm.matching(o)),
205
            "Invalid matching");
206
    } else {
207
      check(mwm.mate(n) == INVALID, "Invalid matching");
208
      check(mwm.nodeValue(n) == 0, "Invalid matching");
209
    }
210
  }
211

	
212
  int dv = 0;
213
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
214
    dv += mwm.nodeValue(n);
215
  }
216

	
217
  for (int i = 0; i < mwm.blossomNum(); ++i) {
218
    check(mwm.blossomValue(i) >= 0, "Invalid blossom value");
219
    check(mwm.blossomSize(i) % 2 == 1, "Even blossom size");
220
    dv += mwm.blossomValue(i) * ((mwm.blossomSize(i) - 1) / 2);
221
  }
222

	
223
  check(pv * mwm.dualScale == dv * 2, "Wrong duality");
224

	
225
  return;
226
}
227

	
228
void checkWeightedPerfectMatching(const SmartGraph& graph,
229
                          const SmartGraph::EdgeMap<int>& weight,
230
                          const MaxWeightedPerfectMatching<SmartGraph>& mwpm) {
231
  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
232
    if (graph.u(e) == graph.v(e)) continue;
233
    int rw = mwpm.nodeValue(graph.u(e)) + mwpm.nodeValue(graph.v(e));
234

	
235
    for (int i = 0; i < mwpm.blossomNum(); ++i) {
236
      bool s = false, t = false;
237
      for (MaxWeightedPerfectMatching<SmartGraph>::BlossomIt n(mwpm, i);
238
           n != INVALID; ++n) {
239
        if (graph.u(e) == n) s = true;
240
        if (graph.v(e) == n) t = true;
241
      }
242
      if (s == true && t == true) {
243
        rw += mwpm.blossomValue(i);
244
      }
245
    }
246
    rw -= weight[e] * mwpm.dualScale;
247

	
248
    check(rw >= 0, "Negative reduced weight");
249
    check(rw == 0 || !mwpm.matching(e),
250
          "Non-zero reduced weight on matching edge");
251
  }
252

	
253
  int pv = 0;
254
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
255
    check(mwpm.matching(n) != INVALID, "Non perfect");
256
    pv += weight[mwpm.matching(n)];
257
    SmartGraph::Node o = graph.target(mwpm.matching(n));
258
    check(mwpm.mate(n) == o, "Invalid matching");
259
    check(mwpm.matching(n) == graph.oppositeArc(mwpm.matching(o)),
260
          "Invalid matching");
261
  }
262

	
263
  int dv = 0;
264
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
265
    dv += mwpm.nodeValue(n);
266
  }
267

	
268
  for (int i = 0; i < mwpm.blossomNum(); ++i) {
269
    check(mwpm.blossomValue(i) >= 0, "Invalid blossom value");
270
    check(mwpm.blossomSize(i) % 2 == 1, "Even blossom size");
271
    dv += mwpm.blossomValue(i) * ((mwpm.blossomSize(i) - 1) / 2);
272
  }
273

	
274
  check(pv * mwpm.dualScale == dv * 2, "Wrong duality");
275

	
276
  return;
277
}
278

	
279

	
280
int main() {
281

	
282
  for (int i = 0; i < lgfn; ++i) {
283
    SmartGraph graph;
284
    SmartGraph::EdgeMap<int> weight(graph);
285

	
286
    istringstream lgfs(lgf[i]);
287
    graphReader(graph, lgfs).
288
      edgeMap("weight", weight).run();
289

	
290
    MaxMatching<SmartGraph> mm(graph);
291
    mm.run();
292
    checkMatching(graph, mm);
293

	
294
    MaxWeightedMatching<SmartGraph> mwm(graph, weight);
295
    mwm.run();
296
    checkWeightedMatching(graph, weight, mwm);
297

	
298
    MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight);
299
    bool perfect = mwpm.run();
300

	
301
    check(perfect == (mm.matchingSize() * 2 == countNodes(graph)),
302
          "Perfect matching found");
303

	
304
    if (perfect) {
305
      checkWeightedPerfectMatching(graph, weight, mwpm);
306
    }
307
  }
308

	
309
  return 0;
310
}
0 comments (0 inline)