[Codeup 1953] B: 畅通工程 并查集+求连通块数(3种写法)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qian2213762498/article/details/81980250

http://codeup.cn/problem.php?cid=100000615&pid=1

问题 B: 畅通工程

时间限制: 1 Sec  内存限制: 32 MB
提交: 111  解决: 65
[提交][状态][讨论版][命题人:外部导入]

题目描述

某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?

输入

测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。 
    注意:两个城市之间可以有多条道路相通,也就是说

    3 3
    1 2
    1 2
    2 1


    这种输入也是合法的
    当N为0时,输入结束,该用例不被处理。

输出

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

样例输入

5 3
1 2
3 2
4 5
0

样例输出

1

思路:

为使得当前的无向图连通:

所需增加的最少边数=当前的连通分量数-1;

于是此题就转化为就:无向图的连通分量数了;

3种写法随便写一个就可以AC;

AC Code

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int nmax=1010;
int father[nmax];
int isRoot[nmax];

int findFather(int u){
	if(u==father[u]) return u;
	else{
		int f=findFather(father[u]);
		father[u]=f;
		return f;
	}
} 

void Union(int u,int v){
	int fu=findFather(u);
	int fv=findFather(v);
	if(fu!=fv){
		father[fu]=fv;
	} 
}

void init(int n){
	for(int i=1;i<=n;i++){
		father[i]=i;
		isRoot[i]=0;
	}
}

int main(int argc, char** argv) {
	int n,m;//点数,边数
	while(cin>>n>>m){
		if(n==0){
			break;
		}
		memset(father,0,sizeof(father));
		memset(isRoot,0,sizeof(isRoot));
		init(n);
		int u,v;
		for(int i=0;i<m;i++){
			cin>>u>>v;
			Union(u,v);
		}
		int ans=0;
		for(int i=1;i<=n;i++){
			if(father[i]==i){
				ans++;
			}
		}
		/*  //计算连通分量 
		int ans=0;
		for(int i=1;i<=n;i++){
			isRoot[findFather(i)]++;
		}
		for(int i=1;i<=n;i++){
			if(isRoot[i]!=0){
				ans++;
			}
		}*/
		//还需要增加的边数=连通分量数-1; 
		cout<<ans-1<<endl;
	} 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qian2213762498/article/details/81980250