某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。
省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。 问最少还需要建设多少条道路?
Input 测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;
随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。注意:两个城市之间可以有多条道路相通,也就是说 3 3 1 2 1 2 2 1 这种输入也是合法的 当N为0时,输入结束,该用例不被处理
#include int pre[1000 ];
int find(int x)
{
int r=x;
while (pre[r ]!=r)
r=pre[r ];
int i=x; int j;
while(i!=r)
{
j=pre[i ];
pre[i ]=r;
i=j;
}
return r;
}
int main()
{
int n,m,p1,p2,i,total,f1,f2;
while(scanf("%d",&n) && n) //读入n,如果n为0,结束
{ //刚开始的时候,有n个城镇,一条路都没有 //那么要修n-1条路才能把它们连起来
total=n-1;
//每个点互相独立,自成一个集合,从1编号到n //所以每个点的上级都是自己
for(i=1;i<=n;i++) { pre[i ]=i; } //共有m条路
scanf("%d",&m); while(m--)
{ //下面这段代码,其实就是join函数,只是稍作改动以适应题目要求
//每读入一条路,看它的端点p1,p2是否已经在一个连通分支里了
scanf("%d %d",&p1,&p2);
f1=find(p1);
f2=find(p2);
//如果是不连通的,那么把这两个分支连起来
//分支的总数就减少了1,还需建的路也就减了1
if(f1!=f2)
{
pre[f2 ]=f1;
total--;
}
//如果两点已经连通了,那么这条路只是在图上增加了一个环 //对连通性没有任何影响,无视掉
}
//最后输出还要修的路条数
printf("%d\n",total);
}
return 0;
}
import java.util.Scanner;
public class test2 {
static int[] pre = new int[1000];// 记录上一级节点
// 查找x的根結點
static int find(int x) {
int r = x;
while (pre[r] != r)//如果自己不是根结点
r = pre[r]; //直到自己是根结点
// 压缩路径
int i = x, temp;
while (i != r) {
temp = pre[i];
pre[i] = r;
i = temp;
}
return r;
}
// 接通
/* static void join(int x ,int y)
{
int fx = find(x);
int fy = find(y);
//如果不接通,连接
if(fx!=fy)
pre[fx]=fy;
}*/
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();// 城市数
int n = sc.nextInt();// 已知道路数
int total = m - 1;// 全部需要M-1条路
// 初始化
for (int i = 1; i <= m; i++)
pre[i] = i;
while (n > 0) {
// 接通已知接通的
int a = sc.nextInt();
int b = sc.nextInt();
int fx = find(a);
int fy = find(b);
// 如果不接通,连接
if (fx != fy) {
pre[fx] = fy;
total--;
}
n--;
}
System.out.println(total);
}
}