村村通
題目描述
某市調查城鎮交通狀況,得到現有城鎮道路統計表。表中列出了每條道路直接連通的城鎮。市政府 "村村通工程"的目標是使全市任何兩個城鎮間都可以實現交通(但不一定有直接的道路相連,只要相互之間可達即可)。請你計算出最少還需要建設多少條道路?
輸入格式 輸入包含若干組測試測試數據,每組測試數據的第一行給出兩個用空格隔開的正整數,分別是城鎮數目 n 和道路數目 m ;隨後的 m 行對應 m 條道路,每行給出一對用空格隔開的正整數,分別是該條道路直接相連的兩個城鎮的編號。簡單起見,城鎮從 1 到 n 編號。
輸出格式 對於每組數據,對應一行一個整數。表示最少還需要建設的道路數目。
注意:兩個城市間可以有多條道路相通。
解題思路
很明顯是可以通過並查集解決的。
首先初始化每一個村都是單獨的節點,都是自己的祖父節點。題目給定了 m 條道路,將每條道路的兩端X,Y合併,即X的祖父節點作爲Y的祖父節點的父節點。
之後我們進行查詢,若某節點的祖父節點是他自己,那麼就找到了樹的一個單獨的分支,那麼我們要做的,就是把這些分支進行連接,得到的就是還需要建設的道路。假設有n個分支,那麼就至少需要n-1條道路可以將其連接,形成樹結構。
代碼如下
#include<bits/stdc++.h>
using namespace std;
int fa[1050];
int find(int x) {
if(fa[x] == x) return x;
return fa[x] = find(fa[x]);
}
int main() {
int n,m;
while(scanf("%d%d",&n,&m)!=EOF) {
if(n == 0) break;
for(int i = 1; i<= n; i++) fa[i] = i;
int a,b;
while(m--) {
scanf("%d%d",&a,&b);
int x = find(a);
int y = find(b);
fa[y] = x;
}
int count = 0;
for(int i = 1; i<= n; i++) {
if(i == fa[i]) count++;
}
printf("%d\n",count-1);
}
}