/* Union-Find algorithm.  Ref: Sedgwick, Chap 30, pg 441 */
#include <iostream.h>
const MAXSIZE = 1000;

typedef int Element;
typedef Element Set;

class UF_DisjointSets 
{
 public:

  UF_DisjointSets(int size) 
  // Constructor.  Initially Elements 0 thru size-1 each is a set of one. 
  ;

  Set Find(Element x)
  // Returns the set (actually the root element of the set) 
  // currently containing x.
  ;

  bool Same_Set_p(Element x, Element y)
  // Returns true iff x and y currently are in the same set.
  { return Find(x) == Find(y); }

  void Union(Element x, Element y)
  // Merge the set containing x and the set containing y into one.
  ;

 protected:
  Element* parent;
  inline bool is_root(Element x) { return parent[x] < 0; }
  inline int size(Element x) { return -parent[x] ; }
  /* convention: 
       parent[x] >= 0 means parent[x] is the parent of x in the tree
       which represents the set currently containing x.
       parent[x] < 0 means x is the root of the tree representing
       the set which contains x, and -parent[x] (a positive number)
       is the number of elements in that set.
  */
     
};


UF_DisjointSets::UF_DisjointSets(int size) 
/* constructor.  initially elements 0 thru size-1 each is a set of one. */
  {
  parent = new(int[size]);
  for (int i = 0; i < size; i++) parent[i] = -1;
  }

Set UF_DisjointSets::Find(Element x)
/* returns the set (actually the root element) of the set currently 
   containing x */
  {
  if (is_root(x))
    return x;
  else
    //return Find(parent[x]; // Basic version of Find 
    return parent[x] = Find(parent[x]); // path compression for better performance
  }

void UF_DisjointSets::Union(Element x, Element y)
/* merge the set containing x and the set containing y into one */
  {
  Set i = Find(x);  Set j = Find(y);  

  //parent[j] = i; // Basic version of Union **

  /** Union with weight balancing for better performance **/
  if (parent[i] < parent[j]) 
    { /* set i had more elements so keep it at root */
    parent[i] += parent[j];  parent[j] = i;
    }
  else
    { /* set j had more elements so keep it at root */
    parent[j] += parent[i];  parent[i] = j;
    }
  }
