並查集解決洛谷P1536村村通

村村通

題目鏈接

題目描述

某市調查城鎮交通狀況,得到現有城鎮道路統計表。表中列出了每條道路直接連通的城鎮。市政府 "村村通工程"的目標是使全市任何兩個城鎮間都可以實現交通(但不一定有直接的道路相連,只要相互之間可達即可)。請你計算出最少還需要建設多少條道路?

輸入格式 輸入包含若干組測試測試數據,每組測試數據的第一行給出兩個用空格隔開的正整數,分別是城鎮數目 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);
	}
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章