Dynamic connectivity --Union-Find

来源:互联网 发布:python工具书 编辑:程序博客网 时间:2024/05/16 05:19

refer to :http://algs4.cs.princeton.edu/15uf/

test date:
10 8

4 3
3 8
6 5
9 4
2 1
5 0
7 2
6 1

/*
discription: n nodes, k linked pairs, calculate total sets
solution: set a same id for the connected nodes
*/


#include <iostream>
using std::cin;
using std::cout;
using std::endl;

class QuickFindUF
{
private:
     int *id;
     int count;
     int num;

public:
     QuickFindUF(int n);
     ~QuickFindUF()
     {
         if (NULL == id)
         {
             delete []id;
             id = NULL;
          }
     }

     int getcnt()
     {
          return count;
     }

     int find(int p)
     {
         return id[p];
     }

     bool connected(int p, int q)
     {
         return id[p] == id[q];
     }

     void unite(int p, int q);

};

QuickFindUF::QuickFindUF(int n)
{
     num = n;
     count = n;
     id = new int[n];
     for (int i = 0; i < n; ++i)
          id[i] = i;

}

void QuickFindUF::unite(int p, int q)
{
     if (connected(p, q))
        return;
     int pid = id[p];
     for (int i = 0; i < num; ++i)
     if (id[i] == pid)
           id[i] = id[q];
     --count;
}

int main()
{
     int n;
     cin >> n;
     QuickFindUF *uf = new QuickFindUF(n);
     int cnt;
     cin >> cnt;
     int p, q;
     for (int i = 0; i < cnt; ++i)
     {
          cin >> p >> q;
          if (uf->connected(p, q))
               continue;
          uf->unite(p, q);
      }
      cout << "the result cnt = " << uf->getcnt() << endl;
      delete uf;
      uf = NULL;

      return 0;
}

-----------------------------
/*
discription: n nodes, k linked pairs, calculate total sets
solution: if <p, q> is linked, set q to p's parent
*/

#include <iostream>
using std::cin;
using std::cout;
using std::endl;

class QuickUnionUF
{
private:
     int *id;
     int count;
     int num;

public:
     QuickUnionUF(int n);
     ~QuickUnionUF()
     {
         if (NULL != id)
        {
            delete []id;
            id = NULL;
         }
     }

     int getcnt()
     {
           return count;
     }

     int find(int p);

     bool connected(int p, int q)
     {
          return find(p) == find(q);
     }

     void unite(int p, int q);
};

QuickUnionUF::QuickUnionUF(int n)
{
      num = n;
      count = n;
      id = new int[n];
      for (int i = 0; i < n; ++i)
           id[i] = i;
}

int QuickUnionUF::find(int p)
{
      while (p != id[p])
           p = id[p];
      return p;
}

void QuickUnionUF::unite(int p, int q)
{
        int i = find(p);
        int j = find(q);
        if (i == j)
             return;
        id[i] = j;
        --count;
}

int main()
{
        int n;
        cin >> n;
        QuickUnionUF *uf = new QuickUnionUF(n);
        int cnt;
        cin >> cnt;
        int p, q;
        for (int i = 0; i < cnt; ++i)
        {
               cin >> p >> q;
               if (uf->connected(p, q))
                     continue;
              uf->unite(p, q);
         }
         cout << "the result cnt = " << uf->getcnt() << endl;
         delete uf;
         uf = NULL;

         return 0;
}

-----------------------------------
/*
discription: n nodes, k linked pairs, calculate total sets
solution: set a same id for the connected nodes,weighted
the size of the tree
*/


#include <iostream>
using std::cin;
using std::cout;
using std::endl;

class WeightedQuickUnion
{
private:
       int *id;  // id[i] = parent of i
       int *sz;  // sz[i] = number of objects in the subtree rooted at i
       int count;// the num of sets
       int num;  // the initial node number

public:
      WeightedQuickUnion(int n);
      ~WeightedQuickUnion()
     {
          if (NULL != id)
         {
                delete []id;
                id = NULL;
          }
          if (NULL != sz)
          {
                delete []sz;
                sz = NULL;
          }
      }

      int getcnt()
      {
              return count;
      }
      //find the root of p
      int find(int p);

      bool connected(int p, int q)
      {
           return find(p) == find(q);
      }

      void unite(int p, int q);
};

WeightedQuickUnion::WeightedQuickUnion(int n)
{
       num = n;
       count = n;
       id = new int[n];
       sz = new int[n];
       if (NULL != id && NULL != sz)
            for (int i = 0; i < num; ++i)
            {
                   id[i] = i;
                   sz[i] = 1;
             }
}

int WeightedQuickUnion::find(int p)
{
       while (p != id[p])
               p = id[p];
       return p;
}

void WeightedQuickUnion::unite(int p, int q)
{
       int i = find(p);
       int j = find(q);
       if (i == j)
              return;
       if (sz[i] < sz[j])
       {
             id[i] = j;
             sz[j] += sz[i];
        }
       else
       {
            id[j] = i;
            sz[i] += sz[j];
        }
        --count;
}

int main()
{
       int n;
       cin >> n;
       WeightedQuickUnion *uf = new WeightedQuickUnion(n);
       int cnt;
       cin >> cnt;
       int p, q;
       for (int i = 0; i < cnt; ++i)
       {
             cin >> p >> q;
             if (uf->connected(p, q))
                 continue;
             uf->unite(p, q);
        }
        cout << "the result cnt = " << uf->getcnt() << endl;
        delete uf;
        uf = NULL;

        return 0;
}

---------------------------------------

/*
discription: on the basis of QuickUnion, compress the path of root
solution: set id[x] = x'root directly,not id[x] = x's parent
*/

#include <iostream>
using std::cin;
using std::cout;
using std::endl;

class QuickUnionPathCompressionUF
{
private:
     int *id;
     int count;
     int num;

public:
     QuickUnionPathCompressionUF(int n);
     ~QuickUnionPathCompressionUF()
     {
         if (NULL != id)
        {
            delete []id;
            id = NULL;
         }
     }

     int getcnt()
     {
           return count;
     }

     int find(int p);

     bool connected(int p, int q)
     {
          return find(p) == find(q);
     }

     void unite(int p, int q);
};

QuickUnionPathCompressionUF::QuickUnionPathCompressionUF(int n)
{
      num = n;
      count = n;
      id = new int[n];
      for (int i = 0; i < n; ++i)
           id[i] = i;
}

int QuickUnionPathCompressionUF::find(int p)
{
   int root = p;
   // find p's root
      while (root != id[root])
           root = id[root];
   // set id[p] to p's root iteratively
   while (root != p)
   {
    // backup p's parent
    int t = id[p];
    // set id[p] to p's root
    id[p] = root;
    p = t;
   }
   return root;
}

void QuickUnionPathCompressionUF::unite(int p, int q)
{
        int i = find(p);
        int j = find(q);
        if (i == j)
             return;
        id[i] = j;
        --count;
}

int main()
{
        int n;
        cin >> n;
        QuickUnionPathCompressionUF *uf = new QuickUnionPathCompressionUF(n);
        int cnt;
        cin >> cnt;
        int p, q;
        for (int i = 0; i < cnt; ++i)
        {
               cin >> p >> q;
               if (uf->connected(p, q))
                     continue;
              uf->unite(p, q);
         }
         cout << "the result cnt = " << uf->getcnt() << endl;
         delete uf;
         uf = NULL;

         return 0;
}

-----------------------------------------

/*
discription: on the basis of WeightedQuickUnion, compress the path of root
solution: set id[x] = x'root directly,not id[x] = x's parent
*/
#include <iostream>
using std::cin;
using std::cout;
using std::endl;

class WeightedQuickUnionPathCompressionUF
{
private:
       int *id;  // id[i] = parent of i
       int *sz;  // sz[i] = number of objects in the subtree rooted at i
       int count;// the num of sets
       int num;  // the initial node number

public:
      WeightedQuickUnionPathCompressionUF(int n);
      ~WeightedQuickUnionPathCompressionUF()
     {
          if (NULL != id)
         {
                delete []id;
                id = NULL;
          }
          if (NULL != sz)
          {
                delete []sz;
                sz = NULL;
          }
      }

      int getcnt()
      {
              return count;
      }
      //find the root of p
      int find(int p);

      bool connected(int p, int q)
      {
           return find(p) == find(q);
      }

      void unite(int p, int q);
};

WeightedQuickUnionPathCompressionUF::WeightedQuickUnionPathCompressionUF(int n)
{
       num = n;
       count = n;
       id = new int[n];
       sz = new int[n];
       if (NULL != id && NULL != sz)
            for (int i = 0; i < num; ++i)
            {
                   id[i] = i;
                   sz[i] = 1;
             }
}

int WeightedQuickUnionPathCompressionUF::find(int p)
{
  
   int root = p;
   // find p's root
      while (root != id[root])
           root = id[root];
   // set id[p] to p's root iteratively
   while (root != p)
   {
    // backup p's parent
    int t = id[p];
    // set id[p] to p's root
    id[p] = root;
    p = t;
   }
   return root;
}

void WeightedQuickUnionPathCompressionUF::unite(int p, int q)
{
       int i = find(p);
       int j = find(q);
       if (i == j)
              return;
       if (sz[i] < sz[j])
       {
             id[i] = j;
             sz[j] += sz[i];
        }
       else
       {
            id[j] = i;
            sz[i] += sz[j];
        }
        --count;
}

int main()
{
       int n;
       cin >> n;
       WeightedQuickUnionPathCompressionUF *uf = new WeightedQuickUnionPathCompressionUF(n);
       int cnt;
       cin >> cnt;
       int p, q;
       for (int i = 0; i < cnt; ++i)
       {
             cin >> p >> q;
             if (uf->connected(p, q))
                 continue;
             uf->unite(p, q);
        }
        cout << "the result cnt = " << uf->getcnt() << endl;
        delete uf;
        uf = NULL;

        return 0;
}

 --------------------------------------

/*
discription: on the basis of WeightedQuickUnion, compress the path of root
and weighted the height of the tree
solution: set id[x] = x'root directly,not id[x] = x's parent and make
the height of the tree as small as possible
*/
#include <iostream>
using std::cin;
using std::cout;
using std::endl;

class WeightedQuickUnionByHeightUF
{
private:
       int *id;  // id[i] = parent of i
       int *hi;  // hi[i] = height of subtree rooted at i
       int count;// the num of sets
       int num;  // the initial node number

public:
      WeightedQuickUnionByHeightUF(int n);
      ~WeightedQuickUnionByHeightUF()
     {
          if (NULL != id)
         {
                delete []id;
                id = NULL;
          }
          if (NULL != hi)
          {
                delete []hi;
                hi = NULL;
          }
      }

      int getcnt()
      {
              return count;
      }
      //find the root of p
      int find(int p);

      bool connected(int p, int q)
      {
           return find(p) == find(q);
      }

      void unite(int p, int q);
};

WeightedQuickUnionByHeightUF::WeightedQuickUnionByHeightUF(int n)
{
       num = n;
       count = n;
       id = new int[n];
       hi = new int[n];
       if (NULL != id && NULL != hi)
            for (int i = 0; i < num; ++i)
            {
                   id[i] = i;
                   hi[i] = 0;
             }
}
// return the root of p
int WeightedQuickUnionByHeightUF::find(int p)
{
 
       int root = p;
       // find p's root
       while (root != id[root])
            root = id[root];
       // set id[p] to p's root iteratively
       while (root != p)
       {
              // backup p's parent
              int t = id[p];
              // set id[p] to p's root
              id[p] = root;
              p = t;
        }
        return root;
}

void WeightedQuickUnionByHeightUF::unite(int p, int q)
{
        int i = find(p);
        int j = find(q);
        if (i == j)
               return;
        // make the low tree pointer to the hign tree
        if (hi[i] < hi[j])
              id[i] = j;    
        else if (hi[i] > hi[j])
             id[j] = i;
        else
        {
             id[i] = j;
             ++hi[j];
         }
          --count;
}

int main()
{
       int n;
       cin >> n;
       WeightedQuickUnionByHeightUF *uf = new WeightedQuickUnionByHeightUF(n);
       int cnt;
       cin >> cnt;
       int p, q;
       for (int i = 0; i < cnt; ++i)
       {
             cin >> p >> q;
             if (uf->connected(p, q))
                 continue;
             uf->unite(p, q);
        }
        cout << "the result cnt = " << uf->getcnt() << endl;
        delete uf;
        uf = NULL;

        return 0;
}

 

原创粉丝点击