简单入门并查集, 以前已经做过,但是代码不太好。DP优化搞上火了,做做别的换换脑子...
以前代码
| Memory: 356K | Time: 32MS | 
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==0) break;
        init(n);
        for (i=0; i<m; i++){
            scanf("%d", &k);
            if (k==0) continue;
            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 | 
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 | 
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 ;
}
 
                    
                     
                    
                 
                    
                 
 
         
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号