并查集
我们可以在一开始把每个元素都看成一棵树,并且根结点的父结点指向自己,在此基础上完成查找、合并操作。
两种优化方法:第一种按秩合并,即每次都把较矮的树并到较高的树中。第二种路径压缩,即让所有的并入的结点都指向整棵树的根结点。
具体代码如下:
1 //并查集 2 class DisjointSet { 3 private: 4 //rank is the height of tree 5 int *father, *rank; 6 public: 7 DisjointSet(int size) { 8 father = new int[size]; 9 rank = new int[size]; 10 for (int i = 0; i < size; ++i) { 11 //initially every node is a tree so father points to itself 12 father[i] = i; 13 rank[i] = 0; 14 } 15 } 16 ~DisjointSet() { 17 delete[] father; 18 delete[] rank; 19 } 20 int find_set(int node) { 21 if (father[node] != node) { 22 //path compression 23 father[node]=find_set(father[node]); 24 } 25 return father[node]; 26 } 27 bool merge(int node1, int node2) { 28 int ancestor1 = find_set(node1); 29 int ancestor2 = find_set(node2); 30 if (ancestor1 != ancestor2) { 31 //rank merge 32 if (rank[ancestor1] > rank[ancestor2]) { 33 swap(ancestor1, ancestor2); 34 } 35 //shorter tree points to higher tree 36 father[ancestor1] = ancestor2; 37 rank[ancestor2] = max(rank[ancestor2], rank[ancestor1] + 1); 38 return true; 39 } 40 return false; 41 } 42 };