并查集

来源:互联网 发布:nymex天然气 数据 编辑:程序博客网 时间:2024/06/05 16:26

并查集是一种用来管理元素分组情况的数据结构。一般用来检查图的连通性。并查集通过树形结构实现,每一个元素对应一个节点,每一个组对应一棵树。


(1)初始化


准备n个节点来表示n个元素,最开始没有边。


(2)合并


从一个组的根向另一个组的根连边,这样两棵树就成了一棵树。


(3)查询


目的是为了知道两个节点是否属于同一个组,我们沿着树向上走,来查询这棵树的根是什么。如果两个节点走到了同一个根,则它们是同一组。


(4)退化


树形结构如果发生退化,那么复杂度就会很高,因此需要避免。我们在合并时,如果两棵树的高度不同,则高度小的向高度大的树连边。


(5)路径压缩


对于每个节点,一旦向上走到了根结点,就把该节点直接和根节点相连。


(6)实现

CODE

#define MAXN 100class DisjointSet{private: int par[MAXN];int rank[MAXN];public:void init(int n){for (int i = 0; i < n; ++i){par[i] = i;rank[i] = 0;}} int find(int x){if (par[x] == x)return x;elsereturn par[x] = find(par[x]);} void unite(int x, int y){x = find(x);y = find(y);if (x == y)return;if (rank[x] < rank[y])par[x] = y;else{par[y] = x;if (rank[x] == rank[y])++rank[x];}} bool same(int x, int y){return find(x) == find(y);}};

实战应用:

POJ1182

CODE

void solve1182(){int ans = 0;DisjointSet D;for (int i = 0; i < K; ++i){int t = T[i];int x = X[i] - 1, y = Y[i] - 1;if (x < 0 || N <= x || y < 0 || N <= y){++ans; continue;}if (t == 1){if (D.same(x, y + N) || D.same(x, y + N * 2))++ans;else{D.unite(x, y);//x-A union y-AD.unite(x + N, y + N);D.unite(x + N * 2, y + N * 2);}}else{if (D.same(x, y) || D.same(x, y + N * 2))++ans;else{D.unite(x + N, y);D.unite(x, y + N * 2);D.unite(x + N * 2, y);}}}printf("%d\n", ans);}


0 0
原创粉丝点击