-
题目描述:
-
某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?
解决:
此题即为并查集的简单应用之一。直接贴代码,在关键之处都有详细注释
#include <iostream>
using namespace std;
int father[1001];//父节点的位置
int size[1001];//当前节点的深度
int Find(int nowloc)
{//查找根节点
while(nowloc != father[nowloc])
{
father[nowloc] = father[father[nowloc]];
nowloc = father[nowloc];
}
return nowloc;
}
bool Union(int first,int second)
{
first = Find(first);
second = Find(second);
if (first == second)
{//属于同一集合
return 0;
}
else
{//不属于同一集合
//将小树合并到大树中
if (size[first] < size[second])
{
father[first] = second;
size[second] += size[first];
}
else
{
father[second] = first;
size[first] += size[second];
}
return 1;
}
}
int main()
{
int N= 0,M = 0;
cin >> N;
while(0 != N)
{
cin >> M;
int count = 0;//计算已经存在的最简单路径的条数
//初始化
for (int i = 0; i <= 1000; ++i)
{
father[i] = i;
size[i] = 1;
}
for (int i = 1; i <= M; ++i)
{
int first,second;
cin >> first >> second;
if ( Union(first,second) == 1)
{
/*如果成功将first节点和second节点连接,因为初始化时认为这两个节点
是不连通的,但是他们两个之间又确实存在一条通路,所以我们将简单通路的个数加1
如果Union返回值为0,则说明first和second之间已经存在直接或者间接的简单路径
所以不用加1,否则会导致重复计算
举例:集合某个时刻的状态如下(1,2,3)(4,5)(6)
现在我们输入(5,6),则很明显,原先5和6之间不存在简单路径,现在就添加一条
现在我们输入(1,2),则很明显,原先1和2之间已经存在简单路径了,再加1就是重复计算
总而言之,对于每个集合内的元素,我们可以简单的认为其之间的路径可以简化为此种形式
X-Y-Z-I-O-T
故我们的count计算的就是其中连接符 - 的数量的多少。
故最后需要新修建的路径条数为N - count - 1。可以自己动手画一画
*/
++count;
}
}
cout << N - count - 1<< endl;
cin >> N;
}
}