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;
}