并查集有两个优化。

首先是初始化:

int fa[maxn], r[maxn];

void init(int n) {
    for (int i=1; i<=n; ++i) {
        fa[i] = i;
        r[i] = 1;
    }
}

优化:

一、按秩合并

描述:就是在对两个不同子集连接时,按照rank来连,也就是rank低的连在rank高的下面。rank高的做父亲节点。

作用,这样类似维护了一棵树,树是rank高的在上。

void unin(int u, int v) { // 非按秩合并
    int fau = find_fa(u);
    int fav = find_fa(v);
    if (fau != fav)
        fa[fav] = fau;
}

  

void unin(int u, int v) { // 按秩合并
    int fau = find_fa(u);
    int fav = find_fa(v);
    if (fau == fav) return;

    if (r[u] < r[v]) fa[fau] = fav;
    else {
        if (r[u] == r[v])
            r[u]++;
        fa[fav] = fau;
    }
}

  

二、路径压缩

描述:假如fa数组已经嵌套了N层,那么传统的做法去找祖先要做N次,当N很大时,这种做法很没效率。

这是朴素查找的代码,适合数据量不大的情况:

int findx(int x)
{
    int r=x;
   while(parent[r] !=r)
        r=parent[r];
   return r;
}

 递归式路径压缩易RE:

int find_fa(int v) { // 递归式路径压缩
    if (fa[v] != v) fa[v] = find_fa(fa[v]);
    return fa[v];
}

 非递归式路径压缩:

 

int find_fa(int v) { // 非递归式路径压缩
    int k, j, r;
    r = v;
    while(r != fa[r])
        r = fa[r]; //找到根节点 记录在r上。
    k = v;
    while(k != r) {
        j = fa[k];
        fa[k] = r;
        k = j;
    }
    return r;
}

  

 

posted on 2016-03-19 21:55  小小八  阅读(209)  评论(0编辑  收藏  举报