gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Bug fix in heap unionfind (ticket #197) The previous bugfix set the minimum value in internal nodes wrongly. It corrects the problem.
0 1 0
default
1 file changed with 4 insertions and 7 deletions:
↑ Collapse diff ↑
Show white space 1536 line context
... ...
@@ -412,1401 +412,1398 @@
412 412
    int size(int cls) const {
413 413
      return classes[cls].size;
414 414
    }
415 415

	
416 416
    /// \brief Splits up the component.
417 417
    ///
418 418
    /// Splitting the component into singleton components (component
419 419
    /// of size one).
420 420
    void split(int cls) {
421 421
      int fdx = classes[cls].firstItem;
422 422
      int idx = items[fdx].next;
423 423
      while (idx != fdx) {
424 424
        int next = items[idx].next;
425 425

	
426 426
        singletonItem(idx);
427 427

	
428 428
        int cdx = newClass();
429 429
        items[idx].parent = ~cdx;
430 430

	
431 431
        laceClass(cdx);
432 432
        classes[cdx].size = 1;
433 433
        classes[cdx].firstItem = idx;
434 434

	
435 435
        idx = next;
436 436
      }
437 437

	
438 438
      items[idx].prev = idx;
439 439
      items[idx].next = idx;
440 440

	
441 441
      classes[~(items[idx].parent)].size = 1;
442 442

	
443 443
    }
444 444

	
445 445
    /// \brief Removes the given element from the structure.
446 446
    ///
447 447
    /// Removes the element from its component and if the component becomes
448 448
    /// empty then removes that component from the component list.
449 449
    ///
450 450
    /// \warning It is an error to remove an element which is not in
451 451
    /// the structure.
452 452
    /// \warning This running time of this operation is proportional to the
453 453
    /// number of the items in this class.
454 454
    void erase(const Item& item) {
455 455
      int idx = index[item];
456 456
      int fdx = items[idx].next;
457 457

	
458 458
      int cdx = classIndex(idx);
459 459
      if (idx == fdx) {
460 460
        unlaceClass(cdx);
461 461
        items[idx].next = firstFreeItem;
462 462
        firstFreeItem = idx;
463 463
        return;
464 464
      } else {
465 465
        classes[cdx].firstItem = fdx;
466 466
        --classes[cdx].size;
467 467
        items[fdx].parent = ~cdx;
468 468

	
469 469
        unlaceItem(idx);
470 470
        idx = items[fdx].next;
471 471
        while (idx != fdx) {
472 472
          items[idx].parent = fdx;
473 473
          idx = items[idx].next;
474 474
        }
475 475

	
476 476
      }
477 477

	
478 478
    }
479 479

	
480 480
    /// \brief Gives back a representant item of the component.
481 481
    ///
482 482
    /// Gives back a representant item of the component.
483 483
    Item item(int cls) const {
484 484
      return items[classes[cls].firstItem].item;
485 485
    }
486 486

	
487 487
    /// \brief Removes the component of the given element from the structure.
488 488
    ///
489 489
    /// Removes the component of the given element from the structure.
490 490
    ///
491 491
    /// \warning It is an error to give an element which is not in the
492 492
    /// structure.
493 493
    void eraseClass(int cls) {
494 494
      int fdx = classes[cls].firstItem;
495 495
      unlaceClass(cls);
496 496
      items[items[fdx].prev].next = firstFreeItem;
497 497
      firstFreeItem = fdx;
498 498
    }
499 499

	
500 500
    /// \brief LEMON style iterator for the representant items.
501 501
    ///
502 502
    /// ClassIt is a lemon style iterator for the components. It iterates
503 503
    /// on the ids of the classes.
504 504
    class ClassIt {
505 505
    public:
506 506
      /// \brief Constructor of the iterator
507 507
      ///
508 508
      /// Constructor of the iterator
509 509
      ClassIt(const UnionFindEnum& ufe) : unionFind(&ufe) {
510 510
        cdx = unionFind->firstClass;
511 511
      }
512 512

	
513 513
      /// \brief Constructor to get invalid iterator
514 514
      ///
515 515
      /// Constructor to get invalid iterator
516 516
      ClassIt(Invalid) : unionFind(0), cdx(-1) {}
517 517

	
518 518
      /// \brief Increment operator
519 519
      ///
520 520
      /// It steps to the next representant item.
521 521
      ClassIt& operator++() {
522 522
        cdx = unionFind->classes[cdx].next;
523 523
        return *this;
524 524
      }
525 525

	
526 526
      /// \brief Conversion operator
527 527
      ///
528 528
      /// It converts the iterator to the current representant item.
529 529
      operator int() const {
530 530
        return cdx;
531 531
      }
532 532

	
533 533
      /// \brief Equality operator
534 534
      ///
535 535
      /// Equality operator
536 536
      bool operator==(const ClassIt& i) {
537 537
        return i.cdx == cdx;
538 538
      }
539 539

	
540 540
      /// \brief Inequality operator
541 541
      ///
542 542
      /// Inequality operator
543 543
      bool operator!=(const ClassIt& i) {
544 544
        return i.cdx != cdx;
545 545
      }
546 546

	
547 547
    private:
548 548
      const UnionFindEnum* unionFind;
549 549
      int cdx;
550 550
    };
551 551

	
552 552
    /// \brief LEMON style iterator for the items of a component.
553 553
    ///
554 554
    /// ClassIt is a lemon style iterator for the components. It iterates
555 555
    /// on the items of a class. By example if you want to iterate on
556 556
    /// each items of each classes then you may write the next code.
557 557
    ///\code
558 558
    /// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
559 559
    ///   std::cout << "Class: ";
560 560
    ///   for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
561 561
    ///     std::cout << toString(iit) << ' ' << std::endl;
562 562
    ///   }
563 563
    ///   std::cout << std::endl;
564 564
    /// }
565 565
    ///\endcode
566 566
    class ItemIt {
567 567
    public:
568 568
      /// \brief Constructor of the iterator
569 569
      ///
570 570
      /// Constructor of the iterator. The iterator iterates
571 571
      /// on the class of the \c item.
572 572
      ItemIt(const UnionFindEnum& ufe, int cls) : unionFind(&ufe) {
573 573
        fdx = idx = unionFind->classes[cls].firstItem;
574 574
      }
575 575

	
576 576
      /// \brief Constructor to get invalid iterator
577 577
      ///
578 578
      /// Constructor to get invalid iterator
579 579
      ItemIt(Invalid) : unionFind(0), idx(-1) {}
580 580

	
581 581
      /// \brief Increment operator
582 582
      ///
583 583
      /// It steps to the next item in the class.
584 584
      ItemIt& operator++() {
585 585
        idx = unionFind->items[idx].next;
586 586
        if (idx == fdx) idx = -1;
587 587
        return *this;
588 588
      }
589 589

	
590 590
      /// \brief Conversion operator
591 591
      ///
592 592
      /// It converts the iterator to the current item.
593 593
      operator const Item&() const {
594 594
        return unionFind->items[idx].item;
595 595
      }
596 596

	
597 597
      /// \brief Equality operator
598 598
      ///
599 599
      /// Equality operator
600 600
      bool operator==(const ItemIt& i) {
601 601
        return i.idx == idx;
602 602
      }
603 603

	
604 604
      /// \brief Inequality operator
605 605
      ///
606 606
      /// Inequality operator
607 607
      bool operator!=(const ItemIt& i) {
608 608
        return i.idx != idx;
609 609
      }
610 610

	
611 611
    private:
612 612
      const UnionFindEnum* unionFind;
613 613
      int idx, fdx;
614 614
    };
615 615

	
616 616
  };
617 617

	
618 618
  /// \ingroup auxdat
619 619
  ///
620 620
  /// \brief A \e Extend-Find data structure implementation which
621 621
  /// is able to enumerate the components.
622 622
  ///
623 623
  /// The class implements an \e Extend-Find data structure which is
624 624
  /// able to enumerate the components and the items in a
625 625
  /// component. The data structure is a simplification of the
626 626
  /// Union-Find structure, and it does not allow to merge two components.
627 627
  ///
628 628
  /// \pre You need to add all the elements by the \ref insert()
629 629
  /// method.
630 630
  template <typename _ItemIntMap>
631 631
  class ExtendFindEnum {
632 632
  public:
633 633

	
634 634
    typedef _ItemIntMap ItemIntMap;
635 635
    typedef typename ItemIntMap::Key Item;
636 636

	
637 637
  private:
638 638

	
639 639
    ItemIntMap& index;
640 640

	
641 641
    struct ItemT {
642 642
      int cls;
643 643
      Item item;
644 644
      int next, prev;
645 645
    };
646 646

	
647 647
    std::vector<ItemT> items;
648 648
    int firstFreeItem;
649 649

	
650 650
    struct ClassT {
651 651
      int firstItem;
652 652
      int next, prev;
653 653
    };
654 654

	
655 655
    std::vector<ClassT> classes;
656 656

	
657 657
    int firstClass, firstFreeClass;
658 658

	
659 659
    int newClass() {
660 660
      if (firstFreeClass != -1) {
661 661
        int cdx = firstFreeClass;
662 662
        firstFreeClass = classes[cdx].next;
663 663
        return cdx;
664 664
      } else {
665 665
        classes.push_back(ClassT());
666 666
        return classes.size() - 1;
667 667
      }
668 668
    }
669 669

	
670 670
    int newItem() {
671 671
      if (firstFreeItem != -1) {
672 672
        int idx = firstFreeItem;
673 673
        firstFreeItem = items[idx].next;
674 674
        return idx;
675 675
      } else {
676 676
        items.push_back(ItemT());
677 677
        return items.size() - 1;
678 678
      }
679 679
    }
680 680

	
681 681
  public:
682 682

	
683 683
    /// \brief Constructor
684 684
    ExtendFindEnum(ItemIntMap& _index)
685 685
      : index(_index), items(), firstFreeItem(-1),
686 686
        classes(), firstClass(-1), firstFreeClass(-1) {}
687 687

	
688 688
    /// \brief Inserts the given element into a new component.
689 689
    ///
690 690
    /// This method creates a new component consisting only of the
691 691
    /// given element.
692 692
    int insert(const Item& item) {
693 693
      int cdx = newClass();
694 694
      classes[cdx].prev = -1;
695 695
      classes[cdx].next = firstClass;
696 696
      if (firstClass != -1) {
697 697
        classes[firstClass].prev = cdx;
698 698
      }
699 699
      firstClass = cdx;
700 700

	
701 701
      int idx = newItem();
702 702
      items[idx].item = item;
703 703
      items[idx].cls = cdx;
704 704
      items[idx].prev = idx;
705 705
      items[idx].next = idx;
706 706

	
707 707
      classes[cdx].firstItem = idx;
708 708

	
709 709
      index.set(item, idx);
710 710

	
711 711
      return cdx;
712 712
    }
713 713

	
714 714
    /// \brief Inserts the given element into the given component.
715 715
    ///
716 716
    /// This methods inserts the element \e item a into the \e cls class.
717 717
    void insert(const Item& item, int cls) {
718 718
      int idx = newItem();
719 719
      int rdx = classes[cls].firstItem;
720 720
      items[idx].item = item;
721 721
      items[idx].cls = cls;
722 722

	
723 723
      items[idx].prev = rdx;
724 724
      items[idx].next = items[rdx].next;
725 725
      items[items[rdx].next].prev = idx;
726 726
      items[rdx].next = idx;
727 727

	
728 728
      index.set(item, idx);
729 729
    }
730 730

	
731 731
    /// \brief Clears the union-find data structure
732 732
    ///
733 733
    /// Erase each item from the data structure.
734 734
    void clear() {
735 735
      items.clear();
736 736
      classes.clear;
737 737
      firstClass = firstFreeClass = firstFreeItem = -1;
738 738
    }
739 739

	
740 740
    /// \brief Gives back the class of the \e item.
741 741
    ///
742 742
    /// Gives back the class of the \e item.
743 743
    int find(const Item &item) const {
744 744
      return items[index[item]].cls;
745 745
    }
746 746

	
747 747
    /// \brief Gives back a representant item of the component.
748 748
    ///
749 749
    /// Gives back a representant item of the component.
750 750
    Item item(int cls) const {
751 751
      return items[classes[cls].firstItem].item;
752 752
    }
753 753

	
754 754
    /// \brief Removes the given element from the structure.
755 755
    ///
756 756
    /// Removes the element from its component and if the component becomes
757 757
    /// empty then removes that component from the component list.
758 758
    ///
759 759
    /// \warning It is an error to remove an element which is not in
760 760
    /// the structure.
761 761
    void erase(const Item &item) {
762 762
      int idx = index[item];
763 763
      int cdx = items[idx].cls;
764 764

	
765 765
      if (idx == items[idx].next) {
766 766
        if (classes[cdx].prev != -1) {
767 767
          classes[classes[cdx].prev].next = classes[cdx].next;
768 768
        } else {
769 769
          firstClass = classes[cdx].next;
770 770
        }
771 771
        if (classes[cdx].next != -1) {
772 772
          classes[classes[cdx].next].prev = classes[cdx].prev;
773 773
        }
774 774
        classes[cdx].next = firstFreeClass;
775 775
        firstFreeClass = cdx;
776 776
      } else {
777 777
        classes[cdx].firstItem = items[idx].next;
778 778
        items[items[idx].next].prev = items[idx].prev;
779 779
        items[items[idx].prev].next = items[idx].next;
780 780
      }
781 781
      items[idx].next = firstFreeItem;
782 782
      firstFreeItem = idx;
783 783

	
784 784
    }
785 785

	
786 786

	
787 787
    /// \brief Removes the component of the given element from the structure.
788 788
    ///
789 789
    /// Removes the component of the given element from the structure.
790 790
    ///
791 791
    /// \warning It is an error to give an element which is not in the
792 792
    /// structure.
793 793
    void eraseClass(int cdx) {
794 794
      int idx = classes[cdx].firstItem;
795 795
      items[items[idx].prev].next = firstFreeItem;
796 796
      firstFreeItem = idx;
797 797

	
798 798
      if (classes[cdx].prev != -1) {
799 799
        classes[classes[cdx].prev].next = classes[cdx].next;
800 800
      } else {
801 801
        firstClass = classes[cdx].next;
802 802
      }
803 803
      if (classes[cdx].next != -1) {
804 804
        classes[classes[cdx].next].prev = classes[cdx].prev;
805 805
      }
806 806
      classes[cdx].next = firstFreeClass;
807 807
      firstFreeClass = cdx;
808 808
    }
809 809

	
810 810
    /// \brief LEMON style iterator for the classes.
811 811
    ///
812 812
    /// ClassIt is a lemon style iterator for the components. It iterates
813 813
    /// on the ids of classes.
814 814
    class ClassIt {
815 815
    public:
816 816
      /// \brief Constructor of the iterator
817 817
      ///
818 818
      /// Constructor of the iterator
819 819
      ClassIt(const ExtendFindEnum& ufe) : extendFind(&ufe) {
820 820
        cdx = extendFind->firstClass;
821 821
      }
822 822

	
823 823
      /// \brief Constructor to get invalid iterator
824 824
      ///
825 825
      /// Constructor to get invalid iterator
826 826
      ClassIt(Invalid) : extendFind(0), cdx(-1) {}
827 827

	
828 828
      /// \brief Increment operator
829 829
      ///
830 830
      /// It steps to the next representant item.
831 831
      ClassIt& operator++() {
832 832
        cdx = extendFind->classes[cdx].next;
833 833
        return *this;
834 834
      }
835 835

	
836 836
      /// \brief Conversion operator
837 837
      ///
838 838
      /// It converts the iterator to the current class id.
839 839
      operator int() const {
840 840
        return cdx;
841 841
      }
842 842

	
843 843
      /// \brief Equality operator
844 844
      ///
845 845
      /// Equality operator
846 846
      bool operator==(const ClassIt& i) {
847 847
        return i.cdx == cdx;
848 848
      }
849 849

	
850 850
      /// \brief Inequality operator
851 851
      ///
852 852
      /// Inequality operator
853 853
      bool operator!=(const ClassIt& i) {
854 854
        return i.cdx != cdx;
855 855
      }
856 856

	
857 857
    private:
858 858
      const ExtendFindEnum* extendFind;
859 859
      int cdx;
860 860
    };
861 861

	
862 862
    /// \brief LEMON style iterator for the items of a component.
863 863
    ///
864 864
    /// ClassIt is a lemon style iterator for the components. It iterates
865 865
    /// on the items of a class. By example if you want to iterate on
866 866
    /// each items of each classes then you may write the next code.
867 867
    ///\code
868 868
    /// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
869 869
    ///   std::cout << "Class: ";
870 870
    ///   for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
871 871
    ///     std::cout << toString(iit) << ' ' << std::endl;
872 872
    ///   }
873 873
    ///   std::cout << std::endl;
874 874
    /// }
875 875
    ///\endcode
876 876
    class ItemIt {
877 877
    public:
878 878
      /// \brief Constructor of the iterator
879 879
      ///
880 880
      /// Constructor of the iterator. The iterator iterates
881 881
      /// on the class of the \c item.
882 882
      ItemIt(const ExtendFindEnum& ufe, int cls) : extendFind(&ufe) {
883 883
        fdx = idx = extendFind->classes[cls].firstItem;
884 884
      }
885 885

	
886 886
      /// \brief Constructor to get invalid iterator
887 887
      ///
888 888
      /// Constructor to get invalid iterator
889 889
      ItemIt(Invalid) : extendFind(0), idx(-1) {}
890 890

	
891 891
      /// \brief Increment operator
892 892
      ///
893 893
      /// It steps to the next item in the class.
894 894
      ItemIt& operator++() {
895 895
        idx = extendFind->items[idx].next;
896 896
        if (fdx == idx) idx = -1;
897 897
        return *this;
898 898
      }
899 899

	
900 900
      /// \brief Conversion operator
901 901
      ///
902 902
      /// It converts the iterator to the current item.
903 903
      operator const Item&() const {
904 904
        return extendFind->items[idx].item;
905 905
      }
906 906

	
907 907
      /// \brief Equality operator
908 908
      ///
909 909
      /// Equality operator
910 910
      bool operator==(const ItemIt& i) {
911 911
        return i.idx == idx;
912 912
      }
913 913

	
914 914
      /// \brief Inequality operator
915 915
      ///
916 916
      /// Inequality operator
917 917
      bool operator!=(const ItemIt& i) {
918 918
        return i.idx != idx;
919 919
      }
920 920

	
921 921
    private:
922 922
      const ExtendFindEnum* extendFind;
923 923
      int idx, fdx;
924 924
    };
925 925

	
926 926
  };
927 927

	
928 928
  /// \ingroup auxdat
929 929
  ///
930 930
  /// \brief A \e Union-Find data structure implementation which
931 931
  /// is able to store a priority for each item and retrieve the minimum of
932 932
  /// each class.
933 933
  ///
934 934
  /// A \e Union-Find data structure implementation which is able to
935 935
  /// store a priority for each item and retrieve the minimum of each
936 936
  /// class. In addition, it supports the joining and splitting the
937 937
  /// components. If you don't need this feature then you makes
938 938
  /// better to use the \ref UnionFind class which is more efficient.
939 939
  ///
940 940
  /// The union-find data strcuture based on a (2, 16)-tree with a
941 941
  /// tournament minimum selection on the internal nodes. The insert
942 942
  /// operation takes O(1), the find, set, decrease and increase takes
943 943
  /// O(log(n)), where n is the number of nodes in the current
944 944
  /// component.  The complexity of join and split is O(log(n)*k),
945 945
  /// where n is the sum of the number of the nodes and k is the
946 946
  /// number of joined components or the number of the components
947 947
  /// after the split.
948 948
  ///
949 949
  /// \pre You need to add all the elements by the \ref insert()
950 950
  /// method.
951 951
  ///
952 952
  template <typename _Value, typename _ItemIntMap,
953 953
            typename _Comp = std::less<_Value> >
954 954
  class HeapUnionFind {
955 955
  public:
956 956

	
957 957
    typedef _Value Value;
958 958
    typedef typename _ItemIntMap::Key Item;
959 959

	
960 960
    typedef _ItemIntMap ItemIntMap;
961 961

	
962 962
    typedef _Comp Comp;
963 963

	
964 964
  private:
965 965

	
966 966
    static const int cmax = 16;
967 967

	
968 968
    ItemIntMap& index;
969 969

	
970 970
    struct ClassNode {
971 971
      int parent;
972 972
      int depth;
973 973

	
974 974
      int left, right;
975 975
      int next, prev;
976 976
    };
977 977

	
978 978
    int first_class;
979 979
    int first_free_class;
980 980
    std::vector<ClassNode> classes;
981 981

	
982 982
    int newClass() {
983 983
      if (first_free_class < 0) {
984 984
        int id = classes.size();
985 985
        classes.push_back(ClassNode());
986 986
        return id;
987 987
      } else {
988 988
        int id = first_free_class;
989 989
        first_free_class = classes[id].next;
990 990
        return id;
991 991
      }
992 992
    }
993 993

	
994 994
    void deleteClass(int id) {
995 995
      classes[id].next = first_free_class;
996 996
      first_free_class = id;
997 997
    }
998 998

	
999 999
    struct ItemNode {
1000 1000
      int parent;
1001 1001
      Item item;
1002 1002
      Value prio;
1003 1003
      int next, prev;
1004 1004
      int left, right;
1005 1005
      int size;
1006 1006
    };
1007 1007

	
1008 1008
    int first_free_node;
1009 1009
    std::vector<ItemNode> nodes;
1010 1010

	
1011 1011
    int newNode() {
1012 1012
      if (first_free_node < 0) {
1013 1013
        int id = nodes.size();
1014 1014
        nodes.push_back(ItemNode());
1015 1015
        return id;
1016 1016
      } else {
1017 1017
        int id = first_free_node;
1018 1018
        first_free_node = nodes[id].next;
1019 1019
        return id;
1020 1020
      }
1021 1021
    }
1022 1022

	
1023 1023
    void deleteNode(int id) {
1024 1024
      nodes[id].next = first_free_node;
1025 1025
      first_free_node = id;
1026 1026
    }
1027 1027

	
1028 1028
    Comp comp;
1029 1029

	
1030 1030
    int findClass(int id) const {
1031 1031
      int kd = id;
1032 1032
      while (kd >= 0) {
1033 1033
        kd = nodes[kd].parent;
1034 1034
      }
1035 1035
      return ~kd;
1036 1036
    }
1037 1037

	
1038 1038
    int leftNode(int id) const {
1039 1039
      int kd = ~(classes[id].parent);
1040 1040
      for (int i = 0; i < classes[id].depth; ++i) {
1041 1041
        kd = nodes[kd].left;
1042 1042
      }
1043 1043
      return kd;
1044 1044
    }
1045 1045

	
1046 1046
    int nextNode(int id) const {
1047 1047
      int depth = 0;
1048 1048
      while (id >= 0 && nodes[id].next == -1) {
1049 1049
        id = nodes[id].parent;
1050 1050
        ++depth;
1051 1051
      }
1052 1052
      if (id < 0) {
1053 1053
        return -1;
1054 1054
      }
1055 1055
      id = nodes[id].next;
1056 1056
      while (depth--) {
1057 1057
        id = nodes[id].left;
1058 1058
      }
1059 1059
      return id;
1060 1060
    }
1061 1061

	
1062 1062

	
1063 1063
    void setPrio(int id) {
1064 1064
      int jd = nodes[id].left;
1065 1065
      nodes[id].prio = nodes[jd].prio;
1066 1066
      nodes[id].item = nodes[jd].item;
1067 1067
      jd = nodes[jd].next;
1068 1068
      while (jd != -1) {
1069 1069
        if (comp(nodes[jd].prio, nodes[id].prio)) {
1070 1070
          nodes[id].prio = nodes[jd].prio;
1071 1071
          nodes[id].item = nodes[jd].item;
1072 1072
        }
1073 1073
        jd = nodes[jd].next;
1074 1074
      }
1075 1075
    }
1076 1076

	
1077 1077
    void push(int id, int jd) {
1078 1078
      nodes[id].size = 1;
1079 1079
      nodes[id].left = nodes[id].right = jd;
1080 1080
      nodes[jd].next = nodes[jd].prev = -1;
1081 1081
      nodes[jd].parent = id;
1082 1082
    }
1083 1083

	
1084 1084
    void pushAfter(int id, int jd) {
1085 1085
      int kd = nodes[id].parent;
1086 1086
      if (nodes[id].next != -1) {
1087 1087
        nodes[nodes[id].next].prev = jd;
1088 1088
        if (kd >= 0) {
1089 1089
          nodes[kd].size += 1;
1090 1090
        }
1091 1091
      } else {
1092 1092
        if (kd >= 0) {
1093 1093
          nodes[kd].right = jd;
1094 1094
          nodes[kd].size += 1;
1095 1095
        }
1096 1096
      }
1097 1097
      nodes[jd].next = nodes[id].next;
1098 1098
      nodes[jd].prev = id;
1099 1099
      nodes[id].next = jd;
1100 1100
      nodes[jd].parent = kd;
1101 1101
    }
1102 1102

	
1103 1103
    void pushRight(int id, int jd) {
1104 1104
      nodes[id].size += 1;
1105 1105
      nodes[jd].prev = nodes[id].right;
1106 1106
      nodes[jd].next = -1;
1107 1107
      nodes[nodes[id].right].next = jd;
1108 1108
      nodes[id].right = jd;
1109 1109
      nodes[jd].parent = id;
1110 1110
    }
1111 1111

	
1112 1112
    void popRight(int id) {
1113 1113
      nodes[id].size -= 1;
1114 1114
      int jd = nodes[id].right;
1115 1115
      nodes[nodes[jd].prev].next = -1;
1116 1116
      nodes[id].right = nodes[jd].prev;
1117 1117
    }
1118 1118

	
1119 1119
    void splice(int id, int jd) {
1120 1120
      nodes[id].size += nodes[jd].size;
1121 1121
      nodes[nodes[id].right].next = nodes[jd].left;
1122 1122
      nodes[nodes[jd].left].prev = nodes[id].right;
1123 1123
      int kd = nodes[jd].left;
1124 1124
      while (kd != -1) {
1125 1125
        nodes[kd].parent = id;
1126 1126
        kd = nodes[kd].next;
1127 1127
      }
1128 1128
      nodes[id].right = nodes[jd].right;
1129 1129
    }
1130 1130

	
1131 1131
    void split(int id, int jd) {
1132 1132
      int kd = nodes[id].parent;
1133 1133
      nodes[kd].right = nodes[id].prev;
1134 1134
      nodes[nodes[id].prev].next = -1;
1135 1135

	
1136 1136
      nodes[jd].left = id;
1137 1137
      nodes[id].prev = -1;
1138 1138
      int num = 0;
1139 1139
      while (id != -1) {
1140 1140
        nodes[id].parent = jd;
1141 1141
        nodes[jd].right = id;
1142 1142
        id = nodes[id].next;
1143 1143
        ++num;
1144 1144
      }
1145 1145
      nodes[kd].size -= num;
1146 1146
      nodes[jd].size = num;
1147 1147
    }
1148 1148

	
1149 1149
    void pushLeft(int id, int jd) {
1150 1150
      nodes[id].size += 1;
1151 1151
      nodes[jd].next = nodes[id].left;
1152 1152
      nodes[jd].prev = -1;
1153 1153
      nodes[nodes[id].left].prev = jd;
1154 1154
      nodes[id].left = jd;
1155 1155
      nodes[jd].parent = id;
1156 1156
    }
1157 1157

	
1158 1158
    void popLeft(int id) {
1159 1159
      nodes[id].size -= 1;
1160 1160
      int jd = nodes[id].left;
1161 1161
      nodes[nodes[jd].next].prev = -1;
1162 1162
      nodes[id].left = nodes[jd].next;
1163 1163
    }
1164 1164

	
1165 1165
    void repairLeft(int id) {
1166 1166
      int jd = ~(classes[id].parent);
1167 1167
      while (nodes[jd].left != -1) {
1168 1168
        int kd = nodes[jd].left;
1169 1169
        if (nodes[jd].size == 1) {
1170 1170
          if (nodes[jd].parent < 0) {
1171 1171
            classes[id].parent = ~kd;
1172 1172
            classes[id].depth -= 1;
1173 1173
            nodes[kd].parent = ~id;
1174 1174
            deleteNode(jd);
1175 1175
            jd = kd;
1176 1176
          } else {
1177 1177
            int pd = nodes[jd].parent;
1178 1178
            if (nodes[nodes[jd].next].size < cmax) {
1179 1179
              pushLeft(nodes[jd].next, nodes[jd].left);
1180
              if (nodes[jd].item == nodes[pd].item) {
1180
              if (less(jd, nodes[jd].next) ||
1181
                  nodes[jd].item == nodes[pd].item) {
1181 1182
                nodes[nodes[jd].next].prio = nodes[jd].prio;
1182 1183
                nodes[nodes[jd].next].item = nodes[jd].item;
1183 1184
              }
1184 1185
              popLeft(pd);
1185 1186
              deleteNode(jd);
1186 1187
              jd = pd;
1187 1188
            } else {
1188 1189
              int ld = nodes[nodes[jd].next].left;
1189 1190
              popLeft(nodes[jd].next);
1190 1191
              pushRight(jd, ld);
1191 1192
              if (less(ld, nodes[jd].left) || 
1192 1193
                  nodes[ld].item == nodes[pd].item) {
1193 1194
                nodes[jd].item = nodes[ld].item;
1194 1195
                nodes[jd].prio = nodes[ld].prio;
1195 1196
              }
1196 1197
              if (nodes[nodes[jd].next].item == nodes[ld].item) {
1197 1198
                setPrio(nodes[jd].next);
1198 1199
              }
1199 1200
              jd = nodes[jd].left;
1200 1201
            }
1201 1202
          }
1202 1203
        } else {
1203 1204
          jd = nodes[jd].left;
1204 1205
        }
1205 1206
      }
1206 1207
    }
1207 1208

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

	
1251 1253

	
1252 1254
    bool less(int id, int jd) const {
1253 1255
      return comp(nodes[id].prio, nodes[jd].prio);
1254 1256
    }
1255 1257

	
1256
    bool equal(int id, int jd) const {
1257
      return !less(id, jd) && !less(jd, id);
1258
    }
1259

	
1260

	
1261 1258
  public:
1262 1259

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

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

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

	
1288 1285
    /// \brief Insert a new node into a new component.
1289 1286
    ///
1290 1287
    /// Insert a new node into a new component.
1291 1288
    /// \param item The item of the new node.
1292 1289
    /// \param prio The priority of the new node.
1293 1290
    /// \return The class id of the one-item-heap.
1294 1291
    int insert(const Item& item, const Value& prio) {
1295 1292
      int id = newNode();
1296 1293
      nodes[id].item = item;
1297 1294
      nodes[id].prio = prio;
1298 1295
      nodes[id].size = 0;
1299 1296

	
1300 1297
      nodes[id].prev = -1;
1301 1298
      nodes[id].next = -1;
1302 1299

	
1303 1300
      nodes[id].left = -1;
1304 1301
      nodes[id].right = -1;
1305 1302

	
1306 1303
      nodes[id].item = item;
1307 1304
      index[item] = id;
1308 1305

	
1309 1306
      int class_id = newClass();
1310 1307
      classes[class_id].parent = ~id;
1311 1308
      classes[class_id].depth = 0;
1312 1309

	
1313 1310
      classes[class_id].left = -1;
1314 1311
      classes[class_id].right = -1;
1315 1312

	
1316 1313
      if (first_class != -1) {
1317 1314
        classes[first_class].prev = class_id;
1318 1315
      }
1319 1316
      classes[class_id].next = first_class;
1320 1317
      classes[class_id].prev = -1;
1321 1318
      first_class = class_id;
1322 1319

	
1323 1320
      nodes[id].parent = ~class_id;
1324 1321

	
1325 1322
      return class_id;
1326 1323
    }
1327 1324

	
1328 1325
    /// \brief The class of the item.
1329 1326
    ///
1330 1327
    /// \return The alive class id of the item, which is not nested into
1331 1328
    /// other classes.
1332 1329
    ///
1333 1330
    /// The time complexity is O(log(n)).
1334 1331
    int find(const Item& item) const {
1335 1332
      return findClass(index[item]);
1336 1333
    }
1337 1334

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

	
1353 1350
      int class_id = newClass();
1354 1351
      { // creation union-find
1355 1352

	
1356 1353
        if (first_class != -1) {
1357 1354
          classes[first_class].prev = class_id;
1358 1355
        }
1359 1356
        classes[class_id].next = first_class;
1360 1357
        classes[class_id].prev = -1;
1361 1358
        first_class = class_id;
1362 1359

	
1363 1360
        classes[class_id].depth = classes[cs[0]].depth;
1364 1361
        classes[class_id].parent = classes[cs[0]].parent;
1365 1362
        nodes[~(classes[class_id].parent)].parent = ~class_id;
1366 1363

	
1367 1364
        int l = cs[0];
1368 1365

	
1369 1366
        classes[class_id].left = l;
1370 1367
        classes[class_id].right = l;
1371 1368

	
1372 1369
        if (classes[l].next != -1) {
1373 1370
          classes[classes[l].next].prev = classes[l].prev;
1374 1371
        }
1375 1372
        classes[classes[l].prev].next = classes[l].next;
1376 1373

	
1377 1374
        classes[l].prev = -1;
1378 1375
        classes[l].next = -1;
1379 1376

	
1380 1377
        classes[l].depth = leftNode(l);
1381 1378
        classes[l].parent = class_id;
1382 1379

	
1383 1380
      }
1384 1381

	
1385 1382
      { // merging of heap
1386 1383
        int l = class_id;
1387 1384
        for (int ci = 1; ci < int(cs.size()); ++ci) {
1388 1385
          int r = cs[ci];
1389 1386
          int rln = leftNode(r);
1390 1387
          if (classes[l].depth > classes[r].depth) {
1391 1388
            int id = ~(classes[l].parent);
1392 1389
            for (int i = classes[r].depth + 1; i < classes[l].depth; ++i) {
1393 1390
              id = nodes[id].right;
1394 1391
            }
1395 1392
            while (id >= 0 && nodes[id].size == cmax) {
1396 1393
              int new_id = newNode();
1397 1394
              int right_id = nodes[id].right;
1398 1395

	
1399 1396
              popRight(id);
1400 1397
              if (nodes[id].item == nodes[right_id].item) {
1401 1398
                setPrio(id);
1402 1399
              }
1403 1400
              push(new_id, right_id);
1404 1401
              pushRight(new_id, ~(classes[r].parent));
1405 1402

	
1406 1403
              if (less(~classes[r].parent, right_id)) {
1407 1404
                nodes[new_id].item = nodes[~classes[r].parent].item;
1408 1405
                nodes[new_id].prio = nodes[~classes[r].parent].prio;
1409 1406
              } else {
1410 1407
                nodes[new_id].item = nodes[right_id].item;
1411 1408
                nodes[new_id].prio = nodes[right_id].prio;
1412 1409
              }
1413 1410

	
1414 1411
              id = nodes[id].parent;
1415 1412
              classes[r].parent = ~new_id;
1416 1413
            }
1417 1414
            if (id < 0) {
1418 1415
              int new_parent = newNode();
1419 1416
              nodes[new_parent].next = -1;
1420 1417
              nodes[new_parent].prev = -1;
1421 1418
              nodes[new_parent].parent = ~l;
1422 1419

	
1423 1420
              push(new_parent, ~(classes[l].parent));
1424 1421
              pushRight(new_parent, ~(classes[r].parent));
1425 1422
              setPrio(new_parent);
1426 1423

	
1427 1424
              classes[l].parent = ~new_parent;
1428 1425
              classes[l].depth += 1;
1429 1426
            } else {
1430 1427
              pushRight(id, ~(classes[r].parent));
1431 1428
              while (id >= 0 && less(~(classes[r].parent), id)) {
1432 1429
                nodes[id].prio = nodes[~(classes[r].parent)].prio;
1433 1430
                nodes[id].item = nodes[~(classes[r].parent)].item;
1434 1431
                id = nodes[id].parent;
1435 1432
              }
1436 1433
            }
1437 1434
          } else if (classes[r].depth > classes[l].depth) {
1438 1435
            int id = ~(classes[r].parent);
1439 1436
            for (int i = classes[l].depth + 1; i < classes[r].depth; ++i) {
1440 1437
              id = nodes[id].left;
1441 1438
            }
1442 1439
            while (id >= 0 && nodes[id].size == cmax) {
1443 1440
              int new_id = newNode();
1444 1441
              int left_id = nodes[id].left;
1445 1442

	
1446 1443
              popLeft(id);
1447 1444
              if (nodes[id].prio == nodes[left_id].prio) {
1448 1445
                setPrio(id);
1449 1446
              }
1450 1447
              push(new_id, left_id);
1451 1448
              pushLeft(new_id, ~(classes[l].parent));
1452 1449

	
1453 1450
              if (less(~classes[l].parent, left_id)) {
1454 1451
                nodes[new_id].item = nodes[~classes[l].parent].item;
1455 1452
                nodes[new_id].prio = nodes[~classes[l].parent].prio;
1456 1453
              } else {
1457 1454
                nodes[new_id].item = nodes[left_id].item;
1458 1455
                nodes[new_id].prio = nodes[left_id].prio;
1459 1456
              }
1460 1457

	
1461 1458
              id = nodes[id].parent;
1462 1459
              classes[l].parent = ~new_id;
1463 1460

	
1464 1461
            }
1465 1462
            if (id < 0) {
1466 1463
              int new_parent = newNode();
1467 1464
              nodes[new_parent].next = -1;
1468 1465
              nodes[new_parent].prev = -1;
1469 1466
              nodes[new_parent].parent = ~l;
1470 1467

	
1471 1468
              push(new_parent, ~(classes[r].parent));
1472 1469
              pushLeft(new_parent, ~(classes[l].parent));
1473 1470
              setPrio(new_parent);
1474 1471

	
1475 1472
              classes[r].parent = ~new_parent;
1476 1473
              classes[r].depth += 1;
1477 1474
            } else {
1478 1475
              pushLeft(id, ~(classes[l].parent));
1479 1476
              while (id >= 0 && less(~(classes[l].parent), id)) {
1480 1477
                nodes[id].prio = nodes[~(classes[l].parent)].prio;
1481 1478
                nodes[id].item = nodes[~(classes[l].parent)].item;
1482 1479
                id = nodes[id].parent;
1483 1480
              }
1484 1481
            }
1485 1482
            nodes[~(classes[r].parent)].parent = ~l;
1486 1483
            classes[l].parent = classes[r].parent;
1487 1484
            classes[l].depth = classes[r].depth;
1488 1485
          } else {
1489 1486
            if (classes[l].depth != 0 &&
1490 1487
                nodes[~(classes[l].parent)].size +
1491 1488
                nodes[~(classes[r].parent)].size <= cmax) {
1492 1489
              splice(~(classes[l].parent), ~(classes[r].parent));
1493 1490
              deleteNode(~(classes[r].parent));
1494 1491
              if (less(~(classes[r].parent), ~(classes[l].parent))) {
1495 1492
                nodes[~(classes[l].parent)].prio =
1496 1493
                  nodes[~(classes[r].parent)].prio;
1497 1494
                nodes[~(classes[l].parent)].item =
1498 1495
                  nodes[~(classes[r].parent)].item;
1499 1496
              }
1500 1497
            } else {
1501 1498
              int new_parent = newNode();
1502 1499
              nodes[new_parent].next = nodes[new_parent].prev = -1;
1503 1500
              push(new_parent, ~(classes[l].parent));
1504 1501
              pushRight(new_parent, ~(classes[r].parent));
1505 1502
              setPrio(new_parent);
1506 1503

	
1507 1504
              classes[l].parent = ~new_parent;
1508 1505
              classes[l].depth += 1;
1509 1506
              nodes[new_parent].parent = ~l;
1510 1507
            }
1511 1508
          }
1512 1509
          if (classes[r].next != -1) {
1513 1510
            classes[classes[r].next].prev = classes[r].prev;
1514 1511
          }
1515 1512
          classes[classes[r].prev].next = classes[r].next;
1516 1513

	
1517 1514
          classes[r].prev = classes[l].right;
1518 1515
          classes[classes[l].right].next = r;
1519 1516
          classes[l].right = r;
1520 1517
          classes[r].parent = l;
1521 1518

	
1522 1519
          classes[r].next = -1;
1523 1520
          classes[r].depth = rln;
1524 1521
        }
1525 1522
      }
1526 1523
      return class_id;
1527 1524
    }
1528 1525

	
1529 1526
    /// \brief Split the class to subclasses.
1530 1527
    ///
1531 1528
    /// The current function splits the given class. The join, which
1532 1529
    /// made the current class, stored a reference to the
1533 1530
    /// subclasses. The \c splitClass() member restores the classes
1534 1531
    /// and creates the heaps. The parameter is an STL output iterator
1535 1532
    /// which will be filled with the subclass ids. The time
1536 1533
    /// complexity is O(log(n)*k) where n is the overall number of
1537 1534
    /// nodes in the splitted classes and k is the number of the
1538 1535
    /// classes.
1539 1536
    template <typename Iterator>
1540 1537
    void split(int cls, Iterator out) {
1541 1538
      std::vector<int> cs;
1542 1539
      { // splitting union-find
1543 1540
        int id = cls;
1544 1541
        int l = classes[id].left;
1545 1542

	
1546 1543
        classes[l].parent = classes[id].parent;
1547 1544
        classes[l].depth = classes[id].depth;
1548 1545

	
1549 1546
        nodes[~(classes[l].parent)].parent = ~l;
1550 1547

	
1551 1548
        *out++ = l;
1552 1549

	
1553 1550
        while (l != -1) {
1554 1551
          cs.push_back(l);
1555 1552
          l = classes[l].next;
1556 1553
        }
1557 1554

	
1558 1555
        classes[classes[id].right].next = first_class;
1559 1556
        classes[first_class].prev = classes[id].right;
1560 1557
        first_class = classes[id].left;
1561 1558

	
1562 1559
        if (classes[id].next != -1) {
1563 1560
          classes[classes[id].next].prev = classes[id].prev;
1564 1561
        }
1565 1562
        classes[classes[id].prev].next = classes[id].next;
1566 1563

	
1567 1564
        deleteClass(id);
1568 1565
      }
1569 1566

	
1570 1567
      {
1571 1568
        for (int i = 1; i < int(cs.size()); ++i) {
1572 1569
          int l = classes[cs[i]].depth;
1573 1570
          while (nodes[nodes[l].parent].left == l) {
1574 1571
            l = nodes[l].parent;
1575 1572
          }
1576 1573
          int r = l;
1577 1574
          while (nodes[l].parent >= 0) {
1578 1575
            l = nodes[l].parent;
1579 1576
            int new_node = newNode();
1580 1577

	
1581 1578
            nodes[new_node].prev = -1;
1582 1579
            nodes[new_node].next = -1;
1583 1580

	
1584 1581
            split(r, new_node);
1585 1582
            pushAfter(l, new_node);
1586 1583
            setPrio(l);
1587 1584
            setPrio(new_node);
1588 1585
            r = new_node;
1589 1586
          }
1590 1587
          classes[cs[i]].parent = ~r;
1591 1588
          classes[cs[i]].depth = classes[~(nodes[l].parent)].depth;
1592 1589
          nodes[r].parent = ~cs[i];
1593 1590

	
1594 1591
          nodes[l].next = -1;
1595 1592
          nodes[r].prev = -1;
1596 1593

	
1597 1594
          repairRight(~(nodes[l].parent));
1598 1595
          repairLeft(cs[i]);
1599 1596

	
1600 1597
          *out++ = cs[i];
1601 1598
        }
1602 1599
      }
1603 1600
    }
1604 1601

	
1605 1602
    /// \brief Gives back the priority of the current item.
1606 1603
    ///
1607 1604
    /// \return Gives back the priority of the current item.
1608 1605
    const Value& operator[](const Item& item) const {
1609 1606
      return nodes[index[item]].prio;
1610 1607
    }
1611 1608

	
1612 1609
    /// \brief Sets the priority of the current item.
1613 1610
    ///
1614 1611
    /// Sets the priority of the current item.
1615 1612
    void set(const Item& item, const Value& prio) {
1616 1613
      if (comp(prio, nodes[index[item]].prio)) {
1617 1614
        decrease(item, prio);
1618 1615
      } else if (!comp(prio, nodes[index[item]].prio)) {
1619 1616
        increase(item, prio);
1620 1617
      }
1621 1618
    }
1622 1619

	
1623 1620
    /// \brief Increase the priority of the current item.
1624 1621
    ///
1625 1622
    /// Increase the priority of the current item.
1626 1623
    void increase(const Item& item, const Value& prio) {
1627 1624
      int id = index[item];
1628 1625
      int kd = nodes[id].parent;
1629 1626
      nodes[id].prio = prio;
1630 1627
      while (kd >= 0 && nodes[kd].item == item) {
1631 1628
        setPrio(kd);
1632 1629
        kd = nodes[kd].parent;
1633 1630
      }
1634 1631
    }
1635 1632

	
1636 1633
    /// \brief Increase the priority of the current item.
1637 1634
    ///
1638 1635
    /// Increase the priority of the current item.
1639 1636
    void decrease(const Item& item, const Value& prio) {
1640 1637
      int id = index[item];
1641 1638
      int kd = nodes[id].parent;
1642 1639
      nodes[id].prio = prio;
1643 1640
      while (kd >= 0 && less(id, kd)) {
1644 1641
        nodes[kd].prio = prio;
1645 1642
        nodes[kd].item = item;
1646 1643
        kd = nodes[kd].parent;
1647 1644
      }
1648 1645
    }
1649 1646

	
1650 1647
    /// \brief Gives back the minimum priority of the class.
1651 1648
    ///
1652 1649
    /// \return Gives back the minimum priority of the class.
1653 1650
    const Value& classPrio(int cls) const {
1654 1651
      return nodes[~(classes[cls].parent)].prio;
1655 1652
    }
1656 1653

	
1657 1654
    /// \brief Gives back the minimum priority item of the class.
1658 1655
    ///
1659 1656
    /// \return Gives back the minimum priority item of the class.
1660 1657
    const Item& classTop(int cls) const {
1661 1658
      return nodes[~(classes[cls].parent)].item;
1662 1659
    }
1663 1660

	
1664 1661
    /// \brief Gives back a representant item of the class.
1665 1662
    ///
1666 1663
    /// The representant is indpendent from the priorities of the
1667 1664
    /// items.
1668 1665
    /// \return Gives back a representant item of the class.
1669 1666
    const Item& classRep(int id) const {
1670 1667
      int parent = classes[id].parent;
1671 1668
      return nodes[parent >= 0 ? classes[id].depth : leftNode(id)].item;
1672 1669
    }
1673 1670

	
1674 1671
    /// \brief LEMON style iterator for the items of a class.
1675 1672
    ///
1676 1673
    /// ClassIt is a lemon style iterator for the components. It iterates
1677 1674
    /// on the items of a class. By example if you want to iterate on
1678 1675
    /// each items of each classes then you may write the next code.
1679 1676
    ///\code
1680 1677
    /// for (ClassIt cit(huf); cit != INVALID; ++cit) {
1681 1678
    ///   std::cout << "Class: ";
1682 1679
    ///   for (ItemIt iit(huf, cit); iit != INVALID; ++iit) {
1683 1680
    ///     std::cout << toString(iit) << ' ' << std::endl;
1684 1681
    ///   }
1685 1682
    ///   std::cout << std::endl;
1686 1683
    /// }
1687 1684
    ///\endcode
1688 1685
    class ItemIt {
1689 1686
    private:
1690 1687

	
1691 1688
      const HeapUnionFind* _huf;
1692 1689
      int _id, _lid;
1693 1690

	
1694 1691
    public:
1695 1692

	
1696 1693
      /// \brief Default constructor
1697 1694
      ///
1698 1695
      /// Default constructor
1699 1696
      ItemIt() {}
1700 1697

	
1701 1698
      ItemIt(const HeapUnionFind& huf, int cls) : _huf(&huf) {
1702 1699
        int id = cls;
1703 1700
        int parent = _huf->classes[id].parent;
1704 1701
        if (parent >= 0) {
1705 1702
          _id = _huf->classes[id].depth;
1706 1703
          if (_huf->classes[id].next != -1) {
1707 1704
            _lid = _huf->classes[_huf->classes[id].next].depth;
1708 1705
          } else {
1709 1706
            _lid = -1;
1710 1707
          }
1711 1708
        } else {
1712 1709
          _id = _huf->leftNode(id);
1713 1710
          _lid = -1;
1714 1711
        }
1715 1712
      }
1716 1713

	
1717 1714
      /// \brief Increment operator
1718 1715
      ///
1719 1716
      /// It steps to the next item in the class.
1720 1717
      ItemIt& operator++() {
1721 1718
        _id = _huf->nextNode(_id);
1722 1719
        return *this;
1723 1720
      }
1724 1721

	
1725 1722
      /// \brief Conversion operator
1726 1723
      ///
1727 1724
      /// It converts the iterator to the current item.
1728 1725
      operator const Item&() const {
1729 1726
        return _huf->nodes[_id].item;
1730 1727
      }
1731 1728

	
1732 1729
      /// \brief Equality operator
1733 1730
      ///
1734 1731
      /// Equality operator
1735 1732
      bool operator==(const ItemIt& i) {
1736 1733
        return i._id == _id;
1737 1734
      }
1738 1735

	
1739 1736
      /// \brief Inequality operator
1740 1737
      ///
1741 1738
      /// Inequality operator
1742 1739
      bool operator!=(const ItemIt& i) {
1743 1740
        return i._id != _id;
1744 1741
      }
1745 1742

	
1746 1743
      /// \brief Equality operator
1747 1744
      ///
1748 1745
      /// Equality operator
1749 1746
      bool operator==(Invalid) {
1750 1747
        return _id == _lid;
1751 1748
      }
1752 1749

	
1753 1750
      /// \brief Inequality operator
1754 1751
      ///
1755 1752
      /// Inequality operator
1756 1753
      bool operator!=(Invalid) {
1757 1754
        return _id != _lid;
1758 1755
      }
1759 1756

	
1760 1757
    };
1761 1758

	
1762 1759
    /// \brief Class iterator
1763 1760
    ///
1764 1761
    /// The iterator stores
1765 1762
    class ClassIt {
1766 1763
    private:
1767 1764

	
1768 1765
      const HeapUnionFind* _huf;
1769 1766
      int _id;
1770 1767

	
1771 1768
    public:
1772 1769

	
1773 1770
      ClassIt(const HeapUnionFind& huf)
1774 1771
        : _huf(&huf), _id(huf.first_class) {}
1775 1772

	
1776 1773
      ClassIt(const HeapUnionFind& huf, int cls)
1777 1774
        : _huf(&huf), _id(huf.classes[cls].left) {}
1778 1775

	
1779 1776
      ClassIt(Invalid) : _huf(0), _id(-1) {}
1780 1777

	
1781 1778
      const ClassIt& operator++() {
1782 1779
        _id = _huf->classes[_id].next;
1783 1780
        return *this;
1784 1781
      }
1785 1782

	
1786 1783
      /// \brief Equality operator
1787 1784
      ///
1788 1785
      /// Equality operator
1789 1786
      bool operator==(const ClassIt& i) {
1790 1787
        return i._id == _id;
1791 1788
      }
1792 1789

	
1793 1790
      /// \brief Inequality operator
1794 1791
      ///
1795 1792
      /// Inequality operator
1796 1793
      bool operator!=(const ClassIt& i) {
1797 1794
        return i._id != _id;
1798 1795
      }
1799 1796

	
1800 1797
      operator int() const {
1801 1798
        return _id;
1802 1799
      }
1803 1800

	
1804 1801
    };
1805 1802

	
1806 1803
  };
1807 1804

	
1808 1805
  //! @}
1809 1806

	
1810 1807
} //namespace lemon
1811 1808

	
1812 1809
#endif //LEMON_UNION_FIND_H
0 comments (0 inline)