poj 1611 The Suspects (并查集)

简单入门并查集, 以前已经做过,但是代码不太好。DP优化搞上火了,做做别的换换脑子...

以前代码 

Memory: 356KTime: 32MS
#include<cstdio>

usingnamespace std;

const int maxn = 30000;

int father[maxn+5];//记录父节点
int len[maxn+5];//记录以该点为根的集合元素的个数

void init(int n){//并查集的初始化
    int i;
    for (i=0; i<n; i++)
    {
        father[i] = i;
        len[i] = 1;
    }
}

inline int getroot(int x){//获得某节点的根节点(不同于父节点),并压缩路径
    int r = x;
    while(father[r]!=r)
        r = father[r];
    while(father[x]!=r){
        father[x] = r;
        x = father[x];
    }
    return r;
}

inline void join(int s, int x){//把s和x合并起来
    int a = getroot(s);
    int b = getroot(x);
    if (a!=b){
        father[a] = b;
        len[b] += len[a];
    }
}

int main(){
    int n, m, k;
    int i, j, x, s;
    while(scanf("%d %d", &n, &m)!=EOF){
        if (n==0 && m==0break;
        init(n);
        for (i=0; i<m; i++){
            scanf("%d", &k);
            if (k==0continue;
            scanf("%d", &s);
            for (j=1; j<k; j++){
                scanf("%d", &x);
                join(s, x);
            }
        }
        printf("%d\n", len[getroot(0)]);
    }
    return 0;
}


不用按秩合并的话

Memory: 284KTime: 16MS

#include<cstdio>
int p[30005] ;
void make_set(int n){
    for(int i=0; i<n; i++)
        p[i] = i ;
}
int find_set(int x){
    if(x!=p[x])
        p[x] = find_set(p[x]) ;
    return p[x] ;
}
void union_set(int x, int y){
    x = find_set(x) ;
    y = find_set(y) ;
    if(x!=y)
        p[y] = x ;
}
int main(){
    int n, m, i, x, y, sum ;
    while(~scanf("%d%d", &n, &m)&&(n+m)){
        make_set(n) ;
        while(m--){
            scanf("%d", &i) ;
            scanf("%d", &x) ;
            i -- ;
            while(i--){
                scanf("%d", &y) ;
                union_set(x, y) ;
            }
        }
        sum = 1 ;
        for(i=1; i<n; i++)
            if(find_set(i)==find_set(0))
                sum ++ ;
        printf("%d\n", sum) ;
    }
    return 0 ;
}

按秩合并 

Memory: 400KTime: 0MS
#include<cstdio> 

int p[30005], r[30005] ;

void make_set(int n){
    for(int i=0; i<n; i++){
        p[i] = i ;
        r[i] = 0 ;
    }
}
int find_set(int x){
    if(x!=p[x])
        p[x] = find_set(p[x]) ;
    return p[x] ;
}
void union_set(int x, int y){
    x = find_set(x) ;
    y = find_set(y) ;
    if(x!=y){
        if(r[x]>r[y])
            p[y] = x ;
        else{
            p[x] = y ;
            if(r[x]==r[y])
                r[y] ++ ;
        }
    }
}
int main(){
    int n, m, i, x, y, sum ;
    while(~scanf("%d%d", &n, &m)&&(n+m)){
        make_set(n) ;
        while(m--){
            scanf("%d", &i) ;
            scanf("%d", &x) ;
            i -- ;
            while(i--){
                scanf("%d", &y) ;
                union_set(x, y) ;
            }
        }
        sum = 1 ;
        for(i=1; i<n; i++)
            if(find_set(i)==find_set(0))
                sum ++ ;
        printf("%d\n", sum) ;
    }
    return 0 ;
}


原文地址:https://www.cnblogs.com/xiaolongchase/p/2332437.html