并查集是一个树形的数据结构,能够实现快速查询两个数是否属于同一个集合。
并查集虽说是树形的结构,但是一个节点只记录了父亲,不记录子节点,因为记录子节点完全没有必要。
怎么标记两个节点属于一个集合?比如两个节点是a和b,则只需要fa(a) = fa(b),fa(a)是a最原始的祖先。这样的话两棵树就连在了一起。要查询两个节点是否在同一个集合,只需要分别计算fa(a)和fa(b),只要两者一样就代表他们在同一颗树,也就是属于同一个集合。
当然,并查集只能只有上述两个操作,不能够修改节点集合之间的关系,也不能嵌套之类的。如果真的要实现这些复杂的操作,那么只能够求靠动态树了。
并查集一个操作的复杂度在于找父亲,可以每次merge的时候让这棵树平衡一点加快并查集的查询速度。
并查集的一个应用就是求最小生成树的kruskal算法。每次选择最短的边,把两个相连的点标记为在同一个集合,知道所有点都加入集合,就得到最小生成树了。
下面是并查集一个实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| |Author: YMC |Created Time: 2015/3/26 22:17:52 |File Name: a.cpp |Description: \***********************************************/ int n,m; int father[5000]; void init(int n) { srep(i,n) father[i] = i; } int find(int v) { return father[v] = father[v] == v ? v : find(father[v]); } bool merge(int a,int b) { int x = find(a); int y = find(b); if(x == y) return false; father[x] = y; return true; }
|