gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Merge #356
0 2 0
merge default
2 files changed with 71 insertions and 2 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
... ...
@@ -717,227 +717,246 @@
717 717
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
718 718

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

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

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

	
729 729
    };
730 730

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

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

	
736 736
    MatchingMap* _matching;
737 737

	
738 738
    NodePotential* _node_potential;
739 739

	
740 740
    BlossomPotential _blossom_potential;
741 741
    BlossomNodeList _blossom_node_list;
742 742

	
743 743
    int _node_num;
744 744
    int _blossom_num;
745 745

	
746 746
    typedef RangeMap<int> IntIntMap;
747 747

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

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

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

	
765 765
    IntNodeMap *_node_index;
766 766
    IntArcMap *_node_heap_index;
767 767

	
768 768
    struct NodeData {
769 769

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

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

	
778 778
      int tree;
779 779
    };
780 780

	
781 781
    RangeMap<NodeData>* _node_data;
782 782

	
783 783
    typedef ExtendFindEnum<IntIntMap> TreeSet;
784 784

	
785 785
    IntIntMap *_tree_set_index;
786 786
    TreeSet *_tree_set;
787 787

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

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

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

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

	
800 800
    Value _delta_sum;
801 801
    int _unmatched;
802 802

	
803 803
    typedef MaxWeightedFractionalMatching<Graph, WeightMap> FractionalMatching;
804 804
    FractionalMatching *_fractional;
805 805

	
806 806
    void createStructures() {
807 807
      _node_num = countNodes(_graph);
808 808
      _blossom_num = _node_num * 3 / 2;
809 809

	
810 810
      if (!_matching) {
811 811
        _matching = new MatchingMap(_graph);
812 812
      }
813

	
813 814
      if (!_node_potential) {
814 815
        _node_potential = new NodePotential(_graph);
815 816
      }
817

	
816 818
      if (!_blossom_set) {
817 819
        _blossom_index = new IntNodeMap(_graph);
818 820
        _blossom_set = new BlossomSet(*_blossom_index);
819 821
        _blossom_data = new RangeMap<BlossomData>(_blossom_num);
822
      } else if (_blossom_data->size() != _blossom_num) {
823
        delete _blossom_data;
824
        _blossom_data = new RangeMap<BlossomData>(_blossom_num);
820 825
      }
821 826

	
822 827
      if (!_node_index) {
823 828
        _node_index = new IntNodeMap(_graph);
824 829
        _node_heap_index = new IntArcMap(_graph);
825 830
        _node_data = new RangeMap<NodeData>(_node_num,
826
                                              NodeData(*_node_heap_index));
831
                                            NodeData(*_node_heap_index));
832
      } else {
833
        delete _node_data;
834
        _node_data = new RangeMap<NodeData>(_node_num,
835
                                            NodeData(*_node_heap_index));
827 836
      }
828 837

	
829 838
      if (!_tree_set) {
830 839
        _tree_set_index = new IntIntMap(_blossom_num);
831 840
        _tree_set = new TreeSet(*_tree_set_index);
841
      } else {
842
        _tree_set_index->resize(_blossom_num);
832 843
      }
844

	
833 845
      if (!_delta1) {
834 846
        _delta1_index = new IntNodeMap(_graph);
835 847
        _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
836 848
      }
849

	
837 850
      if (!_delta2) {
838 851
        _delta2_index = new IntIntMap(_blossom_num);
839 852
        _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
853
      } else {
854
        _delta2_index->resize(_blossom_num);
840 855
      }
856

	
841 857
      if (!_delta3) {
842 858
        _delta3_index = new IntEdgeMap(_graph);
843 859
        _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
844 860
      }
861

	
845 862
      if (!_delta4) {
846 863
        _delta4_index = new IntIntMap(_blossom_num);
847 864
        _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
865
      } else {
866
        _delta4_index->resize(_blossom_num);
848 867
      }
849 868
    }
850 869

	
851 870
    void destroyStructures() {
852 871
      if (_matching) {
853 872
        delete _matching;
854 873
      }
855 874
      if (_node_potential) {
856 875
        delete _node_potential;
857 876
      }
858 877
      if (_blossom_set) {
859 878
        delete _blossom_index;
860 879
        delete _blossom_set;
861 880
        delete _blossom_data;
862 881
      }
863 882

	
864 883
      if (_node_index) {
865 884
        delete _node_index;
866 885
        delete _node_heap_index;
867 886
        delete _node_data;
868 887
      }
869 888

	
870 889
      if (_tree_set) {
871 890
        delete _tree_set_index;
872 891
        delete _tree_set;
873 892
      }
874 893
      if (_delta1) {
875 894
        delete _delta1_index;
876 895
        delete _delta1;
877 896
      }
878 897
      if (_delta2) {
879 898
        delete _delta2_index;
880 899
        delete _delta2;
881 900
      }
882 901
      if (_delta3) {
883 902
        delete _delta3_index;
884 903
        delete _delta3;
885 904
      }
886 905
      if (_delta4) {
887 906
        delete _delta4_index;
888 907
        delete _delta4;
889 908
      }
890 909
    }
891 910

	
892 911
    void matchedToEven(int blossom, int tree) {
893 912
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
894 913
        _delta2->erase(blossom);
895 914
      }
896 915

	
897 916
      if (!_blossom_set->trivial(blossom)) {
898 917
        (*_blossom_data)[blossom].pot -=
899 918
          2 * (_delta_sum - (*_blossom_data)[blossom].offset);
900 919
      }
901 920

	
902 921
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
903 922
           n != INVALID; ++n) {
904 923

	
905 924
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
906 925
        int ni = (*_node_index)[n];
907 926

	
908 927
        (*_node_data)[ni].heap.clear();
909 928
        (*_node_data)[ni].heap_index.clear();
910 929

	
911 930
        (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
912 931

	
913 932
        _delta1->push(n, (*_node_data)[ni].pot);
914 933

	
915 934
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
916 935
          Node v = _graph.source(e);
917 936
          int vb = _blossom_set->find(v);
918 937
          int vi = (*_node_index)[v];
919 938

	
920 939
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
921 940
            dualScale * _weight[e];
922 941

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

	
931 950
            if (it != (*_node_data)[vi].heap_index.end()) {
932 951
              if ((*_node_data)[vi].heap[it->second] > rw) {
933 952
                (*_node_data)[vi].heap.replace(it->second, e);
934 953
                (*_node_data)[vi].heap.decrease(e, rw);
935 954
                it->second = e;
936 955
              }
937 956
            } else {
938 957
              (*_node_data)[vi].heap.push(e, rw);
939 958
              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
940 959
            }
941 960

	
942 961
            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
943 962
              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
... ...
@@ -1495,218 +1514,230 @@
1495 1514
        Value pot = (*_blossom_data)[blossom].pot;
1496 1515
        int bn = _blossom_node_list.size();
1497 1516

	
1498 1517
        std::vector<int> subblossoms;
1499 1518
        _blossom_set->split(blossom, std::back_inserter(subblossoms));
1500 1519
        int b = _blossom_set->find(base);
1501 1520
        int ib = -1;
1502 1521
        for (int i = 0; i < int(subblossoms.size()); ++i) {
1503 1522
          if (subblossoms[i] == b) { ib = i; break; }
1504 1523
        }
1505 1524

	
1506 1525
        for (int i = 1; i < int(subblossoms.size()); i += 2) {
1507 1526
          int sb = subblossoms[(ib + i) % subblossoms.size()];
1508 1527
          int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
1509 1528

	
1510 1529
          Arc m = (*_blossom_data)[tb].next;
1511 1530
          extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
1512 1531
          extractBlossom(tb, _graph.source(m), m);
1513 1532
        }
1514 1533
        extractBlossom(subblossoms[ib], base, matching);
1515 1534

	
1516 1535
        int en = _blossom_node_list.size();
1517 1536

	
1518 1537
        _blossom_potential.push_back(BlossomVariable(bn, en, pot));
1519 1538
      }
1520 1539
    }
1521 1540

	
1522 1541
    void extractMatching() {
1523 1542
      std::vector<int> blossoms;
1524 1543
      for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
1525 1544
        blossoms.push_back(c);
1526 1545
      }
1527 1546

	
1528 1547
      for (int i = 0; i < int(blossoms.size()); ++i) {
1529 1548
        if ((*_blossom_data)[blossoms[i]].next != INVALID) {
1530 1549

	
1531 1550
          Value offset = (*_blossom_data)[blossoms[i]].offset;
1532 1551
          (*_blossom_data)[blossoms[i]].pot += 2 * offset;
1533 1552
          for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
1534 1553
               n != INVALID; ++n) {
1535 1554
            (*_node_data)[(*_node_index)[n]].pot -= offset;
1536 1555
          }
1537 1556

	
1538 1557
          Arc matching = (*_blossom_data)[blossoms[i]].next;
1539 1558
          Node base = _graph.source(matching);
1540 1559
          extractBlossom(blossoms[i], base, matching);
1541 1560
        } else {
1542 1561
          Node base = (*_blossom_data)[blossoms[i]].base;
1543 1562
          extractBlossom(blossoms[i], base, INVALID);
1544 1563
        }
1545 1564
      }
1546 1565
    }
1547 1566

	
1548 1567
  public:
1549 1568

	
1550 1569
    /// \brief Constructor
1551 1570
    ///
1552 1571
    /// Constructor.
1553 1572
    MaxWeightedMatching(const Graph& graph, const WeightMap& weight)
1554 1573
      : _graph(graph), _weight(weight), _matching(0),
1555 1574
        _node_potential(0), _blossom_potential(), _blossom_node_list(),
1556 1575
        _node_num(0), _blossom_num(0),
1557 1576

	
1558 1577
        _blossom_index(0), _blossom_set(0), _blossom_data(0),
1559 1578
        _node_index(0), _node_heap_index(0), _node_data(0),
1560 1579
        _tree_set_index(0), _tree_set(0),
1561 1580

	
1562 1581
        _delta1_index(0), _delta1(0),
1563 1582
        _delta2_index(0), _delta2(0),
1564 1583
        _delta3_index(0), _delta3(0),
1565 1584
        _delta4_index(0), _delta4(0),
1566 1585

	
1567 1586
        _delta_sum(), _unmatched(0),
1568 1587

	
1569 1588
        _fractional(0)
1570 1589
    {}
1571 1590

	
1572 1591
    ~MaxWeightedMatching() {
1573 1592
      destroyStructures();
1574 1593
      if (_fractional) {
1575 1594
        delete _fractional;
1576 1595
      }
1577 1596
    }
1578 1597

	
1579 1598
    /// \name Execution Control
1580 1599
    /// The simplest way to execute the algorithm is to use the
1581 1600
    /// \ref run() member function.
1582 1601

	
1583 1602
    ///@{
1584 1603

	
1585 1604
    /// \brief Initialize the algorithm
1586 1605
    ///
1587 1606
    /// This function initializes the algorithm.
1588 1607
    void init() {
1589 1608
      createStructures();
1590 1609

	
1610
      _blossom_node_list.clear();
1611
      _blossom_potential.clear();
1612

	
1591 1613
      for (ArcIt e(_graph); e != INVALID; ++e) {
1592 1614
        (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
1593 1615
      }
1594 1616
      for (NodeIt n(_graph); n != INVALID; ++n) {
1595 1617
        (*_delta1_index)[n] = _delta1->PRE_HEAP;
1596 1618
      }
1597 1619
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1598 1620
        (*_delta3_index)[e] = _delta3->PRE_HEAP;
1599 1621
      }
1600 1622
      for (int i = 0; i < _blossom_num; ++i) {
1601 1623
        (*_delta2_index)[i] = _delta2->PRE_HEAP;
1602 1624
        (*_delta4_index)[i] = _delta4->PRE_HEAP;
1603 1625
      }
1604

	
1626
      
1605 1627
      _unmatched = _node_num;
1606 1628

	
1629
      _delta1->clear();
1630
      _delta2->clear();
1631
      _delta3->clear();
1632
      _delta4->clear();
1633
      _blossom_set->clear();
1634
      _tree_set->clear();
1635

	
1607 1636
      int index = 0;
1608 1637
      for (NodeIt n(_graph); n != INVALID; ++n) {
1609 1638
        Value max = 0;
1610 1639
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1611 1640
          if (_graph.target(e) == n) continue;
1612 1641
          if ((dualScale * _weight[e]) / 2 > max) {
1613 1642
            max = (dualScale * _weight[e]) / 2;
1614 1643
          }
1615 1644
        }
1616 1645
        (*_node_index)[n] = index;
1646
        (*_node_data)[index].heap_index.clear();
1647
        (*_node_data)[index].heap.clear();
1617 1648
        (*_node_data)[index].pot = max;
1618 1649
        _delta1->push(n, max);
1619 1650
        int blossom =
1620 1651
          _blossom_set->insert(n, std::numeric_limits<Value>::max());
1621 1652

	
1622 1653
        _tree_set->insert(blossom);
1623 1654

	
1624 1655
        (*_blossom_data)[blossom].status = EVEN;
1625 1656
        (*_blossom_data)[blossom].pred = INVALID;
1626 1657
        (*_blossom_data)[blossom].next = INVALID;
1627 1658
        (*_blossom_data)[blossom].pot = 0;
1628 1659
        (*_blossom_data)[blossom].offset = 0;
1629 1660
        ++index;
1630 1661
      }
1631 1662
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1632 1663
        int si = (*_node_index)[_graph.u(e)];
1633 1664
        int ti = (*_node_index)[_graph.v(e)];
1634 1665
        if (_graph.u(e) != _graph.v(e)) {
1635 1666
          _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
1636 1667
                            dualScale * _weight[e]) / 2);
1637 1668
        }
1638 1669
      }
1639 1670
    }
1640 1671

	
1641 1672
    /// \brief Initialize the algorithm with fractional matching
1642 1673
    ///
1643 1674
    /// This function initializes the algorithm with a fractional
1644 1675
    /// matching. This initialization is also called jumpstart heuristic.
1645 1676
    void fractionalInit() {
1646 1677
      createStructures();
1647 1678
      
1648 1679
      if (_fractional == 0) {
1649 1680
        _fractional = new FractionalMatching(_graph, _weight, false);
1650 1681
      }
1651 1682
      _fractional->run();
1652 1683

	
1653 1684
      for (ArcIt e(_graph); e != INVALID; ++e) {
1654 1685
        (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
1655 1686
      }
1656 1687
      for (NodeIt n(_graph); n != INVALID; ++n) {
1657 1688
        (*_delta1_index)[n] = _delta1->PRE_HEAP;
1658 1689
      }
1659 1690
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1660 1691
        (*_delta3_index)[e] = _delta3->PRE_HEAP;
1661 1692
      }
1662 1693
      for (int i = 0; i < _blossom_num; ++i) {
1663 1694
        (*_delta2_index)[i] = _delta2->PRE_HEAP;
1664 1695
        (*_delta4_index)[i] = _delta4->PRE_HEAP;
1665 1696
      }
1666 1697

	
1667 1698
      _unmatched = 0;
1668 1699

	
1669 1700
      int index = 0;
1670 1701
      for (NodeIt n(_graph); n != INVALID; ++n) {
1671 1702
        Value pot = _fractional->nodeValue(n);
1672 1703
        (*_node_index)[n] = index;
1673 1704
        (*_node_data)[index].pot = pot;
1674 1705
        int blossom =
1675 1706
          _blossom_set->insert(n, std::numeric_limits<Value>::max());
1676 1707

	
1677 1708
        (*_blossom_data)[blossom].status = MATCHED;
1678 1709
        (*_blossom_data)[blossom].pred = INVALID;
1679 1710
        (*_blossom_data)[blossom].next = _fractional->matching(n);
1680 1711
        if (_fractional->matching(n) == INVALID) {
1681 1712
          (*_blossom_data)[blossom].base = n;
1682 1713
        }
1683 1714
        (*_blossom_data)[blossom].pot = 0;
1684 1715
        (*_blossom_data)[blossom].offset = 0;
1685 1716
        ++index;
1686 1717
      }
1687 1718

	
1688 1719
      typename Graph::template NodeMap<bool> processed(_graph, false);
1689 1720
      for (NodeIt n(_graph); n != INVALID; ++n) {
1690 1721
        if (processed[n]) continue;
1691 1722
        processed[n] = true;
1692 1723
        if (_fractional->matching(n) == INVALID) continue;
1693 1724
        int num = 1;
1694 1725
        Node v = _graph.target(_fractional->matching(n));
1695 1726
        while (n != v) {
1696 1727
          processed[v] = true;
1697 1728
          v = _graph.target(_fractional->matching(v));
1698 1729
          ++num;
1699 1730
        }
1700 1731

	
1701 1732
        if (num % 2 == 1) {
1702 1733
          std::vector<int> subblossoms(num);
1703 1734

	
1704 1735
          subblossoms[--num] = _blossom_set->find(n);
1705 1736
          _delta1->push(n, _fractional->nodeValue(n));
1706 1737
          v = _graph.target(_fractional->matching(n));
1707 1738
          while (n != v) {
1708 1739
            subblossoms[--num] = _blossom_set->find(v);
1709 1740
            _delta1->push(v, _fractional->nodeValue(v));
1710 1741
            v = _graph.target(_fractional->matching(v));            
1711 1742
          }
1712 1743
          
... ...
@@ -2144,223 +2175,241 @@
2144 2175

	
2145 2176
  private:
2146 2177

	
2147 2178
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
2148 2179

	
2149 2180
    typedef typename Graph::template NodeMap<Value> NodePotential;
2150 2181
    typedef std::vector<Node> BlossomNodeList;
2151 2182

	
2152 2183
    struct BlossomVariable {
2153 2184
      int begin, end;
2154 2185
      Value value;
2155 2186

	
2156 2187
      BlossomVariable(int _begin, int _end, Value _value)
2157 2188
        : begin(_begin), end(_end), value(_value) {}
2158 2189

	
2159 2190
    };
2160 2191

	
2161 2192
    typedef std::vector<BlossomVariable> BlossomPotential;
2162 2193

	
2163 2194
    const Graph& _graph;
2164 2195
    const WeightMap& _weight;
2165 2196

	
2166 2197
    MatchingMap* _matching;
2167 2198

	
2168 2199
    NodePotential* _node_potential;
2169 2200

	
2170 2201
    BlossomPotential _blossom_potential;
2171 2202
    BlossomNodeList _blossom_node_list;
2172 2203

	
2173 2204
    int _node_num;
2174 2205
    int _blossom_num;
2175 2206

	
2176 2207
    typedef RangeMap<int> IntIntMap;
2177 2208

	
2178 2209
    enum Status {
2179 2210
      EVEN = -1, MATCHED = 0, ODD = 1
2180 2211
    };
2181 2212

	
2182 2213
    typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
2183 2214
    struct BlossomData {
2184 2215
      int tree;
2185 2216
      Status status;
2186 2217
      Arc pred, next;
2187 2218
      Value pot, offset;
2188 2219
    };
2189 2220

	
2190 2221
    IntNodeMap *_blossom_index;
2191 2222
    BlossomSet *_blossom_set;
2192 2223
    RangeMap<BlossomData>* _blossom_data;
2193 2224

	
2194 2225
    IntNodeMap *_node_index;
2195 2226
    IntArcMap *_node_heap_index;
2196 2227

	
2197 2228
    struct NodeData {
2198 2229

	
2199 2230
      NodeData(IntArcMap& node_heap_index)
2200 2231
        : heap(node_heap_index) {}
2201 2232

	
2202 2233
      int blossom;
2203 2234
      Value pot;
2204 2235
      BinHeap<Value, IntArcMap> heap;
2205 2236
      std::map<int, Arc> heap_index;
2206 2237

	
2207 2238
      int tree;
2208 2239
    };
2209 2240

	
2210 2241
    RangeMap<NodeData>* _node_data;
2211 2242

	
2212 2243
    typedef ExtendFindEnum<IntIntMap> TreeSet;
2213 2244

	
2214 2245
    IntIntMap *_tree_set_index;
2215 2246
    TreeSet *_tree_set;
2216 2247

	
2217 2248
    IntIntMap *_delta2_index;
2218 2249
    BinHeap<Value, IntIntMap> *_delta2;
2219 2250

	
2220 2251
    IntEdgeMap *_delta3_index;
2221 2252
    BinHeap<Value, IntEdgeMap> *_delta3;
2222 2253

	
2223 2254
    IntIntMap *_delta4_index;
2224 2255
    BinHeap<Value, IntIntMap> *_delta4;
2225 2256

	
2226 2257
    Value _delta_sum;
2227 2258
    int _unmatched;
2228 2259

	
2229 2260
    typedef MaxWeightedPerfectFractionalMatching<Graph, WeightMap> 
2230 2261
    FractionalMatching;
2231 2262
    FractionalMatching *_fractional;
2232 2263

	
2233 2264
    void createStructures() {
2234 2265
      _node_num = countNodes(_graph);
2235 2266
      _blossom_num = _node_num * 3 / 2;
2236 2267

	
2237 2268
      if (!_matching) {
2238 2269
        _matching = new MatchingMap(_graph);
2239 2270
      }
2271

	
2240 2272
      if (!_node_potential) {
2241 2273
        _node_potential = new NodePotential(_graph);
2242 2274
      }
2275

	
2243 2276
      if (!_blossom_set) {
2244 2277
        _blossom_index = new IntNodeMap(_graph);
2245 2278
        _blossom_set = new BlossomSet(*_blossom_index);
2246 2279
        _blossom_data = new RangeMap<BlossomData>(_blossom_num);
2280
      } else if (_blossom_data->size() != _blossom_num) {
2281
        delete _blossom_data;
2282
        _blossom_data = new RangeMap<BlossomData>(_blossom_num);
2247 2283
      }
2248 2284

	
2249 2285
      if (!_node_index) {
2250 2286
        _node_index = new IntNodeMap(_graph);
2251 2287
        _node_heap_index = new IntArcMap(_graph);
2252 2288
        _node_data = new RangeMap<NodeData>(_node_num,
2253 2289
                                            NodeData(*_node_heap_index));
2290
      } else if (_node_data->size() != _node_num) {
2291
        delete _node_data;
2292
        _node_data = new RangeMap<NodeData>(_node_num,
2293
                                            NodeData(*_node_heap_index));
2254 2294
      }
2255 2295

	
2256 2296
      if (!_tree_set) {
2257 2297
        _tree_set_index = new IntIntMap(_blossom_num);
2258 2298
        _tree_set = new TreeSet(*_tree_set_index);
2299
      } else {
2300
        _tree_set_index->resize(_blossom_num);
2259 2301
      }
2302

	
2260 2303
      if (!_delta2) {
2261 2304
        _delta2_index = new IntIntMap(_blossom_num);
2262 2305
        _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
2306
      } else {
2307
        _delta2_index->resize(_blossom_num);
2263 2308
      }
2309

	
2264 2310
      if (!_delta3) {
2265 2311
        _delta3_index = new IntEdgeMap(_graph);
2266 2312
        _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
2267 2313
      }
2314

	
2268 2315
      if (!_delta4) {
2269 2316
        _delta4_index = new IntIntMap(_blossom_num);
2270 2317
        _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
2318
      } else {
2319
        _delta4_index->resize(_blossom_num);
2271 2320
      }
2272 2321
    }
2273 2322

	
2274 2323
    void destroyStructures() {
2275 2324
      if (_matching) {
2276 2325
        delete _matching;
2277 2326
      }
2278 2327
      if (_node_potential) {
2279 2328
        delete _node_potential;
2280 2329
      }
2281 2330
      if (_blossom_set) {
2282 2331
        delete _blossom_index;
2283 2332
        delete _blossom_set;
2284 2333
        delete _blossom_data;
2285 2334
      }
2286 2335

	
2287 2336
      if (_node_index) {
2288 2337
        delete _node_index;
2289 2338
        delete _node_heap_index;
2290 2339
        delete _node_data;
2291 2340
      }
2292 2341

	
2293 2342
      if (_tree_set) {
2294 2343
        delete _tree_set_index;
2295 2344
        delete _tree_set;
2296 2345
      }
2297 2346
      if (_delta2) {
2298 2347
        delete _delta2_index;
2299 2348
        delete _delta2;
2300 2349
      }
2301 2350
      if (_delta3) {
2302 2351
        delete _delta3_index;
2303 2352
        delete _delta3;
2304 2353
      }
2305 2354
      if (_delta4) {
2306 2355
        delete _delta4_index;
2307 2356
        delete _delta4;
2308 2357
      }
2309 2358
    }
2310 2359

	
2311 2360
    void matchedToEven(int blossom, int tree) {
2312 2361
      if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2313 2362
        _delta2->erase(blossom);
2314 2363
      }
2315 2364

	
2316 2365
      if (!_blossom_set->trivial(blossom)) {
2317 2366
        (*_blossom_data)[blossom].pot -=
2318 2367
          2 * (_delta_sum - (*_blossom_data)[blossom].offset);
2319 2368
      }
2320 2369

	
2321 2370
      for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2322 2371
           n != INVALID; ++n) {
2323 2372

	
2324 2373
        _blossom_set->increase(n, std::numeric_limits<Value>::max());
2325 2374
        int ni = (*_node_index)[n];
2326 2375

	
2327 2376
        (*_node_data)[ni].heap.clear();
2328 2377
        (*_node_data)[ni].heap_index.clear();
2329 2378

	
2330 2379
        (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
2331 2380

	
2332 2381
        for (InArcIt e(_graph, n); e != INVALID; ++e) {
2333 2382
          Node v = _graph.source(e);
2334 2383
          int vb = _blossom_set->find(v);
2335 2384
          int vi = (*_node_index)[v];
2336 2385

	
2337 2386
          Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2338 2387
            dualScale * _weight[e];
2339 2388

	
2340 2389
          if ((*_blossom_data)[vb].status == EVEN) {
2341 2390
            if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2342 2391
              _delta3->push(e, rw / 2);
2343 2392
            }
2344 2393
          } else {
2345 2394
            typename std::map<int, Arc>::iterator it =
2346 2395
              (*_node_data)[vi].heap_index.find(tree);
2347 2396

	
2348 2397
            if (it != (*_node_data)[vi].heap_index.end()) {
2349 2398
              if ((*_node_data)[vi].heap[it->second] > rw) {
2350 2399
                (*_node_data)[vi].heap.replace(it->second, e);
2351 2400
                (*_node_data)[vi].heap.decrease(e, rw);
2352 2401
                it->second = e;
2353 2402
              }
2354 2403
            } else {
2355 2404
              (*_node_data)[vi].heap.push(e, rw);
2356 2405
              (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2357 2406
            }
2358 2407

	
2359 2408
            if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2360 2409
              _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2361 2410

	
2362 2411
              if ((*_blossom_data)[vb].status == MATCHED) {
2363 2412
                if (_delta2->state(vb) != _delta2->IN_HEAP) {
2364 2413
                  _delta2->push(vb, _blossom_set->classPrio(vb) -
2365 2414
                               (*_blossom_data)[vb].offset);
2366 2415
                } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
... ...
@@ -2875,215 +2924,226 @@
2875 2924

	
2876 2925
        (*_matching)[base] = matching;
2877 2926
        _blossom_node_list.push_back(base);
2878 2927
        (*_node_potential)[base] = pot;
2879 2928
      } else {
2880 2929

	
2881 2930
        Value pot = (*_blossom_data)[blossom].pot;
2882 2931
        int bn = _blossom_node_list.size();
2883 2932

	
2884 2933
        std::vector<int> subblossoms;
2885 2934
        _blossom_set->split(blossom, std::back_inserter(subblossoms));
2886 2935
        int b = _blossom_set->find(base);
2887 2936
        int ib = -1;
2888 2937
        for (int i = 0; i < int(subblossoms.size()); ++i) {
2889 2938
          if (subblossoms[i] == b) { ib = i; break; }
2890 2939
        }
2891 2940

	
2892 2941
        for (int i = 1; i < int(subblossoms.size()); i += 2) {
2893 2942
          int sb = subblossoms[(ib + i) % subblossoms.size()];
2894 2943
          int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
2895 2944

	
2896 2945
          Arc m = (*_blossom_data)[tb].next;
2897 2946
          extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
2898 2947
          extractBlossom(tb, _graph.source(m), m);
2899 2948
        }
2900 2949
        extractBlossom(subblossoms[ib], base, matching);
2901 2950

	
2902 2951
        int en = _blossom_node_list.size();
2903 2952

	
2904 2953
        _blossom_potential.push_back(BlossomVariable(bn, en, pot));
2905 2954
      }
2906 2955
    }
2907 2956

	
2908 2957
    void extractMatching() {
2909 2958
      std::vector<int> blossoms;
2910 2959
      for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
2911 2960
        blossoms.push_back(c);
2912 2961
      }
2913 2962

	
2914 2963
      for (int i = 0; i < int(blossoms.size()); ++i) {
2915 2964

	
2916 2965
        Value offset = (*_blossom_data)[blossoms[i]].offset;
2917 2966
        (*_blossom_data)[blossoms[i]].pot += 2 * offset;
2918 2967
        for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
2919 2968
             n != INVALID; ++n) {
2920 2969
          (*_node_data)[(*_node_index)[n]].pot -= offset;
2921 2970
        }
2922 2971

	
2923 2972
        Arc matching = (*_blossom_data)[blossoms[i]].next;
2924 2973
        Node base = _graph.source(matching);
2925 2974
        extractBlossom(blossoms[i], base, matching);
2926 2975
      }
2927 2976
    }
2928 2977

	
2929 2978
  public:
2930 2979

	
2931 2980
    /// \brief Constructor
2932 2981
    ///
2933 2982
    /// Constructor.
2934 2983
    MaxWeightedPerfectMatching(const Graph& graph, const WeightMap& weight)
2935 2984
      : _graph(graph), _weight(weight), _matching(0),
2936 2985
        _node_potential(0), _blossom_potential(), _blossom_node_list(),
2937 2986
        _node_num(0), _blossom_num(0),
2938 2987

	
2939 2988
        _blossom_index(0), _blossom_set(0), _blossom_data(0),
2940 2989
        _node_index(0), _node_heap_index(0), _node_data(0),
2941 2990
        _tree_set_index(0), _tree_set(0),
2942 2991

	
2943 2992
        _delta2_index(0), _delta2(0),
2944 2993
        _delta3_index(0), _delta3(0),
2945 2994
        _delta4_index(0), _delta4(0),
2946 2995

	
2947 2996
        _delta_sum(), _unmatched(0),
2948 2997

	
2949 2998
        _fractional(0)
2950 2999
    {}
2951 3000

	
2952 3001
    ~MaxWeightedPerfectMatching() {
2953 3002
      destroyStructures();
2954 3003
      if (_fractional) {
2955 3004
        delete _fractional;
2956 3005
      }
2957 3006
    }
2958 3007

	
2959 3008
    /// \name Execution Control
2960 3009
    /// The simplest way to execute the algorithm is to use the
2961 3010
    /// \ref run() member function.
2962 3011

	
2963 3012
    ///@{
2964 3013

	
2965 3014
    /// \brief Initialize the algorithm
2966 3015
    ///
2967 3016
    /// This function initializes the algorithm.
2968 3017
    void init() {
2969 3018
      createStructures();
2970 3019

	
3020
      _blossom_node_list.clear();
3021
      _blossom_potential.clear();
3022

	
2971 3023
      for (ArcIt e(_graph); e != INVALID; ++e) {
2972 3024
        (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
2973 3025
      }
2974 3026
      for (EdgeIt e(_graph); e != INVALID; ++e) {
2975 3027
        (*_delta3_index)[e] = _delta3->PRE_HEAP;
2976 3028
      }
2977 3029
      for (int i = 0; i < _blossom_num; ++i) {
2978 3030
        (*_delta2_index)[i] = _delta2->PRE_HEAP;
2979 3031
        (*_delta4_index)[i] = _delta4->PRE_HEAP;
2980 3032
      }
2981 3033

	
2982 3034
      _unmatched = _node_num;
2983 3035

	
3036
      _delta2->clear();
3037
      _delta3->clear();
3038
      _delta4->clear();
3039
      _blossom_set->clear();
3040
      _tree_set->clear();
3041

	
2984 3042
      int index = 0;
2985 3043
      for (NodeIt n(_graph); n != INVALID; ++n) {
2986 3044
        Value max = - std::numeric_limits<Value>::max();
2987 3045
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
2988 3046
          if (_graph.target(e) == n) continue;
2989 3047
          if ((dualScale * _weight[e]) / 2 > max) {
2990 3048
            max = (dualScale * _weight[e]) / 2;
2991 3049
          }
2992 3050
        }
2993 3051
        (*_node_index)[n] = index;
3052
        (*_node_data)[index].heap_index.clear();
3053
        (*_node_data)[index].heap.clear();
2994 3054
        (*_node_data)[index].pot = max;
2995 3055
        int blossom =
2996 3056
          _blossom_set->insert(n, std::numeric_limits<Value>::max());
2997 3057

	
2998 3058
        _tree_set->insert(blossom);
2999 3059

	
3000 3060
        (*_blossom_data)[blossom].status = EVEN;
3001 3061
        (*_blossom_data)[blossom].pred = INVALID;
3002 3062
        (*_blossom_data)[blossom].next = INVALID;
3003 3063
        (*_blossom_data)[blossom].pot = 0;
3004 3064
        (*_blossom_data)[blossom].offset = 0;
3005 3065
        ++index;
3006 3066
      }
3007 3067
      for (EdgeIt e(_graph); e != INVALID; ++e) {
3008 3068
        int si = (*_node_index)[_graph.u(e)];
3009 3069
        int ti = (*_node_index)[_graph.v(e)];
3010 3070
        if (_graph.u(e) != _graph.v(e)) {
3011 3071
          _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
3012 3072
                            dualScale * _weight[e]) / 2);
3013 3073
        }
3014 3074
      }
3015 3075
    }
3016 3076

	
3017 3077
    /// \brief Initialize the algorithm with fractional matching
3018 3078
    ///
3019 3079
    /// This function initializes the algorithm with a fractional
3020 3080
    /// matching. This initialization is also called jumpstart heuristic.
3021 3081
    void fractionalInit() {
3022 3082
      createStructures();
3023 3083
      
3024 3084
      if (_fractional == 0) {
3025 3085
        _fractional = new FractionalMatching(_graph, _weight, false);
3026 3086
      }
3027 3087
      if (!_fractional->run()) {
3028 3088
        _unmatched = -1;
3029 3089
        return;
3030 3090
      }
3031 3091

	
3032 3092
      for (ArcIt e(_graph); e != INVALID; ++e) {
3033 3093
        (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
3034 3094
      }
3035 3095
      for (EdgeIt e(_graph); e != INVALID; ++e) {
3036 3096
        (*_delta3_index)[e] = _delta3->PRE_HEAP;
3037 3097
      }
3038 3098
      for (int i = 0; i < _blossom_num; ++i) {
3039 3099
        (*_delta2_index)[i] = _delta2->PRE_HEAP;
3040 3100
        (*_delta4_index)[i] = _delta4->PRE_HEAP;
3041 3101
      }
3042 3102

	
3043 3103
      _unmatched = 0;
3044 3104

	
3045 3105
      int index = 0;
3046 3106
      for (NodeIt n(_graph); n != INVALID; ++n) {
3047 3107
        Value pot = _fractional->nodeValue(n);
3048 3108
        (*_node_index)[n] = index;
3049 3109
        (*_node_data)[index].pot = pot;
3050 3110
        int blossom =
3051 3111
          _blossom_set->insert(n, std::numeric_limits<Value>::max());
3052 3112

	
3053 3113
        (*_blossom_data)[blossom].status = MATCHED;
3054 3114
        (*_blossom_data)[blossom].pred = INVALID;
3055 3115
        (*_blossom_data)[blossom].next = _fractional->matching(n);
3056 3116
        (*_blossom_data)[blossom].pot = 0;
3057 3117
        (*_blossom_data)[blossom].offset = 0;
3058 3118
        ++index;
3059 3119
      }
3060 3120

	
3061 3121
      typename Graph::template NodeMap<bool> processed(_graph, false);
3062 3122
      for (NodeIt n(_graph); n != INVALID; ++n) {
3063 3123
        if (processed[n]) continue;
3064 3124
        processed[n] = true;
3065 3125
        if (_fractional->matching(n) == INVALID) continue;
3066 3126
        int num = 1;
3067 3127
        Node v = _graph.target(_fractional->matching(n));
3068 3128
        while (n != v) {
3069 3129
          processed[v] = true;
3070 3130
          v = _graph.target(_fractional->matching(v));
3071 3131
          ++num;
3072 3132
        }
3073 3133

	
3074 3134
        if (num % 2 == 1) {
3075 3135
          std::vector<int> subblossoms(num);
3076 3136

	
3077 3137
          subblossoms[--num] = _blossom_set->find(n);
3078 3138
          v = _graph.target(_fractional->matching(n));
3079 3139
          while (n != v) {
3080 3140
            subblossoms[--num] = _blossom_set->find(v);
3081 3141
            v = _graph.target(_fractional->matching(v));            
3082 3142
          }
3083 3143
          
3084 3144
          int surface = 
3085 3145
            _blossom_set->join(subblossoms.begin(), subblossoms.end());
3086 3146
          (*_blossom_data)[surface].status = EVEN;
3087 3147
          (*_blossom_data)[surface].pred = INVALID;
3088 3148
          (*_blossom_data)[surface].next = INVALID;
3089 3149
          (*_blossom_data)[surface].pot = 0;
Ignore white space 192 line context
... ...
@@ -1195,192 +1195,201 @@
1195 1195
              int ld = nodes[nodes[jd].next].left;
1196 1196
              popLeft(nodes[jd].next);
1197 1197
              pushRight(jd, ld);
1198 1198
              if (less(ld, nodes[jd].left) ||
1199 1199
                  nodes[ld].item == nodes[pd].item) {
1200 1200
                nodes[jd].item = nodes[ld].item;
1201 1201
                nodes[jd].prio = nodes[ld].prio;
1202 1202
              }
1203 1203
              if (nodes[nodes[jd].next].item == nodes[ld].item) {
1204 1204
                setPrio(nodes[jd].next);
1205 1205
              }
1206 1206
              jd = nodes[jd].left;
1207 1207
            }
1208 1208
          }
1209 1209
        } else {
1210 1210
          jd = nodes[jd].left;
1211 1211
        }
1212 1212
      }
1213 1213
    }
1214 1214

	
1215 1215
    void repairRight(int id) {
1216 1216
      int jd = ~(classes[id].parent);
1217 1217
      while (nodes[jd].right != -1) {
1218 1218
        int kd = nodes[jd].right;
1219 1219
        if (nodes[jd].size == 1) {
1220 1220
          if (nodes[jd].parent < 0) {
1221 1221
            classes[id].parent = ~kd;
1222 1222
            classes[id].depth -= 1;
1223 1223
            nodes[kd].parent = ~id;
1224 1224
            deleteNode(jd);
1225 1225
            jd = kd;
1226 1226
          } else {
1227 1227
            int pd = nodes[jd].parent;
1228 1228
            if (nodes[nodes[jd].prev].size < cmax) {
1229 1229
              pushRight(nodes[jd].prev, nodes[jd].right);
1230 1230
              if (less(jd, nodes[jd].prev) ||
1231 1231
                  nodes[jd].item == nodes[pd].item) {
1232 1232
                nodes[nodes[jd].prev].prio = nodes[jd].prio;
1233 1233
                nodes[nodes[jd].prev].item = nodes[jd].item;
1234 1234
              }
1235 1235
              popRight(pd);
1236 1236
              deleteNode(jd);
1237 1237
              jd = pd;
1238 1238
            } else {
1239 1239
              int ld = nodes[nodes[jd].prev].right;
1240 1240
              popRight(nodes[jd].prev);
1241 1241
              pushLeft(jd, ld);
1242 1242
              if (less(ld, nodes[jd].right) ||
1243 1243
                  nodes[ld].item == nodes[pd].item) {
1244 1244
                nodes[jd].item = nodes[ld].item;
1245 1245
                nodes[jd].prio = nodes[ld].prio;
1246 1246
              }
1247 1247
              if (nodes[nodes[jd].prev].item == nodes[ld].item) {
1248 1248
                setPrio(nodes[jd].prev);
1249 1249
              }
1250 1250
              jd = nodes[jd].right;
1251 1251
            }
1252 1252
          }
1253 1253
        } else {
1254 1254
          jd = nodes[jd].right;
1255 1255
        }
1256 1256
      }
1257 1257
    }
1258 1258

	
1259 1259

	
1260 1260
    bool less(int id, int jd) const {
1261 1261
      return comp(nodes[id].prio, nodes[jd].prio);
1262 1262
    }
1263 1263

	
1264 1264
  public:
1265 1265

	
1266 1266
    /// \brief Returns true when the given class is alive.
1267 1267
    ///
1268 1268
    /// Returns true when the given class is alive, ie. the class is
1269 1269
    /// not nested into other class.
1270 1270
    bool alive(int cls) const {
1271 1271
      return classes[cls].parent < 0;
1272 1272
    }
1273 1273

	
1274 1274
    /// \brief Returns true when the given class is trivial.
1275 1275
    ///
1276 1276
    /// Returns true when the given class is trivial, ie. the class
1277 1277
    /// contains just one item directly.
1278 1278
    bool trivial(int cls) const {
1279 1279
      return classes[cls].left == -1;
1280 1280
    }
1281 1281

	
1282 1282
    /// \brief Constructs the union-find.
1283 1283
    ///
1284 1284
    /// Constructs the union-find.
1285 1285
    /// \brief _index The index map of the union-find. The data
1286 1286
    /// structure uses internally for store references.
1287 1287
    HeapUnionFind(ItemIntMap& _index)
1288 1288
      : index(_index), first_class(-1),
1289 1289
        first_free_class(-1), first_free_node(-1) {}
1290 1290

	
1291
    /// \brief Clears the union-find data structure
1292
    ///
1293
    /// Erase each item from the data structure.
1294
    void clear() {
1295
      nodes.clear();
1296
      classes.clear();
1297
      first_free_node = first_free_class = first_class = -1;
1298
    }
1299

	
1291 1300
    /// \brief Insert a new node into a new component.
1292 1301
    ///
1293 1302
    /// Insert a new node into a new component.
1294 1303
    /// \param item The item of the new node.
1295 1304
    /// \param prio The priority of the new node.
1296 1305
    /// \return The class id of the one-item-heap.
1297 1306
    int insert(const Item& item, const Value& prio) {
1298 1307
      int id = newNode();
1299 1308
      nodes[id].item = item;
1300 1309
      nodes[id].prio = prio;
1301 1310
      nodes[id].size = 0;
1302 1311

	
1303 1312
      nodes[id].prev = -1;
1304 1313
      nodes[id].next = -1;
1305 1314

	
1306 1315
      nodes[id].left = -1;
1307 1316
      nodes[id].right = -1;
1308 1317

	
1309 1318
      nodes[id].item = item;
1310 1319
      index[item] = id;
1311 1320

	
1312 1321
      int class_id = newClass();
1313 1322
      classes[class_id].parent = ~id;
1314 1323
      classes[class_id].depth = 0;
1315 1324

	
1316 1325
      classes[class_id].left = -1;
1317 1326
      classes[class_id].right = -1;
1318 1327

	
1319 1328
      if (first_class != -1) {
1320 1329
        classes[first_class].prev = class_id;
1321 1330
      }
1322 1331
      classes[class_id].next = first_class;
1323 1332
      classes[class_id].prev = -1;
1324 1333
      first_class = class_id;
1325 1334

	
1326 1335
      nodes[id].parent = ~class_id;
1327 1336

	
1328 1337
      return class_id;
1329 1338
    }
1330 1339

	
1331 1340
    /// \brief The class of the item.
1332 1341
    ///
1333 1342
    /// \return The alive class id of the item, which is not nested into
1334 1343
    /// other classes.
1335 1344
    ///
1336 1345
    /// The time complexity is O(log(n)).
1337 1346
    int find(const Item& item) const {
1338 1347
      return findClass(index[item]);
1339 1348
    }
1340 1349

	
1341 1350
    /// \brief Joins the classes.
1342 1351
    ///
1343 1352
    /// The current function joins the given classes. The parameter is
1344 1353
    /// an STL range which should be contains valid class ids. The
1345 1354
    /// time complexity is O(log(n)*k) where n is the overall number
1346 1355
    /// of the joined nodes and k is the number of classes.
1347 1356
    /// \return The class of the joined classes.
1348 1357
    /// \pre The range should contain at least two class ids.
1349 1358
    template <typename Iterator>
1350 1359
    int join(Iterator begin, Iterator end) {
1351 1360
      std::vector<int> cs;
1352 1361
      for (Iterator it = begin; it != end; ++it) {
1353 1362
        cs.push_back(*it);
1354 1363
      }
1355 1364

	
1356 1365
      int class_id = newClass();
1357 1366
      { // creation union-find
1358 1367

	
1359 1368
        if (first_class != -1) {
1360 1369
          classes[first_class].prev = class_id;
1361 1370
        }
1362 1371
        classes[class_id].next = first_class;
1363 1372
        classes[class_id].prev = -1;
1364 1373
        first_class = class_id;
1365 1374

	
1366 1375
        classes[class_id].depth = classes[cs[0]].depth;
1367 1376
        classes[class_id].parent = classes[cs[0]].parent;
1368 1377
        nodes[~(classes[class_id].parent)].parent = ~class_id;
1369 1378

	
1370 1379
        int l = cs[0];
1371 1380

	
1372 1381
        classes[class_id].left = l;
1373 1382
        classes[class_id].right = l;
1374 1383

	
1375 1384
        if (classes[l].next != -1) {
1376 1385
          classes[classes[l].next].prev = classes[l].prev;
1377 1386
        }
1378 1387
        classes[classes[l].prev].next = classes[l].next;
1379 1388

	
1380 1389
        classes[l].prev = -1;
1381 1390
        classes[l].next = -1;
1382 1391

	
1383 1392
        classes[l].depth = leftNode(l);
1384 1393
        classes[l].parent = class_id;
1385 1394

	
1386 1395
      }
0 comments (0 inline)