题意是给第一行两个数,n是城市数,m是给出的已经形成通路的道路数,求还需要多少个通道才能使每两个城市之间都形成通路。
上篇博客文章讲了并查集,知道了并查集就很容易做出来,可以这样想,由给出的数据先算出目前已经有了多少个互相形成同路的集合
拿题目中给出的数据举个例子
4 2
1 3
4 3
其中 1 3 4 已经形成通路,2单独形成一个通路,因此如果想要城市之间两两形成同路,则只需要再构成一个2和1,3,4任意一个城市的通路即可。故存在两个集合则
需要再修answer=1条路。依次类推,每次根据数据先算出共有几个集合,answer就是集合数目-1。
代码如下
#include<cstdio>
#include<iostream>
using namespace std;
int pre[2000];
int Find(int x)
{
int r=x;
while(r!=pre[r])//若r的前导点不是它本身
{
r=pre[r];//查找
}
//路径压缩
int i=x,j;
while(pre[i]!=r)
{
j=pre[i];
pre[i]=r;
i=j;
}
return r;//返回查找到的根节点
}
//合并
void join(int x,int y)
{
int rx=Find(x),ry=Find(y);
//cout<<"rx="<<rx<<" ry="<<ry<<endl;
if(rx!=ry)
{
pre[rx]=ry;
}
}
int main()
{
int n,m;
while(cin>>n>>m&&n)
{
int answer;
if(!n)
break;
for(int i=1; i<=n; ++i)
pre[i]=i;//初始化
int a,b;
for(int i=1; i<=m; ++i)
{
cin>>a>>b;
join(a,b);
}
int i;
for(answer=0,i=1; i<=n; ++i)
{
if(i==pre[i])
++answer;
//cout<<pre[i]<<" ";
}
cout<<answer-1<<endl;
}
}