[算法设计与分析] 村村通 (并查集)

luogu P1536

并查集板子题

 1 //
 2 //  main.cpp
 3 //  村村通
 4 //
 5 //  Created by sylvia on 2021/10/30.
 6 //  Copyright © 2021 apple. All rights reserved.
 7 //
 8 /*
 9  并查集板子题
10  建立好并查集后只需要枚举每个点,如果点的父亲是自己就把ans+1
11  最后输出的ans-1即可
12  实质是搜索有多少不联通的块
13 */
14 #include <iostream>
15 #include <stdio.h>
16 #include <math.h>
17 #include <algorithm>
18 #include <string.h>
19 using namespace std;
20 #define M 1000+5
21 
22 
23 int V,E;  //顶点数与边数
24 int father[M],rankk[M];
25 int u,v,ans=0;
26 void init(int n){//并查集初始化
27     for (int i=0;i<n;i++){
28         father[i]=i;
29         rankk[i]=0;
30     }
31 }
32 int find(int x){
33     int j,k,r;
34     r=x;
35     while (r!=father[r]) r=father[r];
36     k=x;
37     while (k!=r){
38         j=father[k];
39         father[k]=r;
40         k=j;
41     }
42     return r;
43 }
44 void unite(int x,int y){  //合并集合
45     x=find(x);
46     y=find(y);
47     if(x==y) return;
48     if (rankk[x]<rankk[y]) father[x]=y;
49     else {
50         father[y]=x;
51         if(rankk[x]==rankk[y]) rankk[x]++;
52     }
53 }
54 int same(int x,int y){  //判断是否在一个集合
55     return find(x)==find(y);
56 }
57 
58 
59 int main(){
60     while ((cin>>V>>E)&&(V!=0)){
61         ans=0;
62         init(V);
63         for (int i=0;i<E;i++){
64             cin>>u>>v;
65             unite(u-1,v-1);
66         }
67         for (int i=0;i<V;i++)
68             if(father[i]==i) ans++;
69         cout<<ans-1<<endl;
70     }
71     return 0;
72 }

 

posted @ 2021-10-30 15:30  Sylvia_lee  阅读(45)  评论(0编辑  收藏  举报