[算法设计与分析] 村村通 (并查集)
并查集板子题
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 }