并查集实现算法

畅通工程 2

题目描述:

某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省

政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相

连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?

输入描述:

测试输入包含若干测试用例。每个测试用例的第 1 行给出两个正整数,分别是城镇数目 N ( <

1000 )和道路数目 M;随后的 M 行对应 M 条道路,每行给出一对正整数,分别是该条道路直接

连通的两个城镇的编号。为简单起见,城镇从 1 到 N 编号。

注意:两个城市之间可以有多条道路相通,也就是说

3 3
1 2
1 2
2 1

这种输入也是合法的

当 N 为 0 时,输入结束,该用例不被处理。

输出描述:

对每个测试用例,在 1 行里输出最少还需要建设的道路数目。

输入样例#:

4 2
1 3
4 3
3 3
1 2
1 3
2 3
5 2
1 2
3 5
999 0
0

输出样例#:

1
0
2
998

题目来源:

DreamJudge 1319

#include
#include
#include
#include
#include
#include
using namespace std;
vector<int> fa; // 存储父节点
int find(int x) {
	if (x == fa[x]) return x; // 如果 x 是根节点,返回 x
	fa[x] = find(fa[x]); // 路径压缩
	return fa[x]; // 返回 x 的根节点
}

void unionSet(int x, int y) {
	int fx = find(x); // 查找 x 的根节点
	int fy = find(y); // 查找 y 的根节点
	if (fx != fy) {
		fa[fx] = fy; // 合并两个集合
	}
}
void solve(){
	//多组输入的情况
	int N, M;
	while (cin >> N) { // 读取城镇数量 N
		if (N == 0) break; // 如果 N 为 0,则结束输入
		cin >> M; // 读取道路数量 M
		fa.resize(N + 1);
		for (int i = 0; i < N + 1; ++i) {// 初始化并查集,大小为 N + 1
			fa[i] = i;}  // 初始化每个节点的父节点为自己
		
		int count = 0; // 记录合并次数
		for (int i = 0; i < M; i++) {
			int x, y;
			cin >> x >> y; // 读取每条道路的两个城镇
			if (find(x) != find(y)) { // 如果 x 和 y 不在同一集合
				unionSet(x, y); // 合并两个集合
				count++; 
			}
		}
		
		cout << N - count - 1 << endl; // N-count表示连通分量数量	
	}
	
	
}
int main(){
	solve();
	return 0;
	}

你可能感兴趣的:(算法,算法,服务器,c++)