poj 1611 The Suspects (并查集)

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

以前代码 

Memory: 356K Time: 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: 284K Time: 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: 400K Time: 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 ;
}


你可能感兴趣的:(poj)