[演算法設計與分析] 村村通 (並查集)
阿新 • • 發佈:2021-10-30
並查集板子題
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(intx){ 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 }