题目描述:
省政府畅通工程的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路连通,只要互相间接通过道路可达即可)。问至少还需要建设多少条道路?
输入:
测试输入包含若干测试用例。每个测试用例的第一行给出两个正整数,分别是城镇数目N(<1000)和道路数目M,随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。当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
示例代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()){
int n = scanner.nextInt();
if (n==0){break;}
Unionset city = new Unionset(n);
int m = scanner.nextInt();
for (int i=0;i<m;i++){
int firstnode = scanner.nextInt();
int secondnode = scanner.nextInt();
city.unionTowns(firstnode,secondnode);
}
int sets = city.setsNumber(n,city);
System.out.println(sets);
}
}
}
//并查集类
public class Unionset {
int size;
int[] towns;
int[] weight;
public Unionset(int size){
this.size = size;
towns = new int[size+1];
weight = new int[size+1];
for (int i=1;i<=size;i++){
towns[i]=i;
weight[i]=1;
}
}
public int findroot(int town_num){
if (town_num==towns[town_num]){return town_num;}
else {
int root_num = findroot(towns[town_num]);
towns[town_num]=root_num;
return root_num;
}
}
public void unionTowns(int firstTnmb,int secondTnmb){
int firstroot = findroot(firstTnmb);
int secondroot = findroot(secondTnmb);
if (firstroot==secondroot){return;}
else {
int firstweight = weight[firstroot];
int secondweight = weight[secondroot];
if (firstweight<=secondweight){towns[firstroot]=secondroot;weight[secondroot]+=firstweight;}
else {towns[secondroot]=firstroot;weight[firstroot]+=secondweight;}
}
}
public int setsNumber(int size,Unionset city){
int sets = -1;
int[] towns = city.towns;
for (int j=1;j<=size;j++){
int tmp = towns[j];
if (tmp==j){sets++;}
}
return sets;
}
}