已知有n个村庄,要实现各个村庄之间互通,已知各个村庄之间修路的费用,要求实现各个村庄之间互通后所需修路费用的最小值。第一行输入n(村庄的总数),接下来的n*(n-1)/2行中,每行输入三个数,前两个数是两个村庄的序号,第三个数是在前两个村庄之间修路的费用。
这显然是一个最小生成树的问题。如果通过Kruskal算法实现,则需要从费用最小的路进行修起,同时还要判断下一次输入的两个村庄中是否已经通过其它村庄联通。
对于例题中的输入,我们可以通过一个结构数组实现。相关代码如下:
struct road
{
int village1, village2, money;
bool judge = false;
};
road结构体中的village1与village2表示两个不同的村庄,money表示在两个村庄之间修路所需要的费用,bool型变量judge的作用在下文中会给出。
在构建road结构体后,我们还需要一个二维数组,类似于邻接矩阵,我们用它来表示哪几个村庄之间已经联通:如果联通,相应的值为1,否则为0。
对于结构数组的输入,相信大家已经对此很熟悉了,下面直接给出代码:
road *information = new road[n];
int *store_money = new int[n], n1 = n * (n - 1) / 2, count = 0, ans = 0;
for (int i = 0; i <n1; i++)
{
cin >> information[i].village1 >> information[i].village2 >> information[i].money;
store_money[i] = information[i].money;
}
或许有人会问上述代码中的store_money数组有什么作用,其实,它是用来存储任意两个村庄之间的修路费用。因为Kruskal算法是从最小费用开始的,而输入顺序是任意的,因此我们只需将任意两个村庄之间的修路费用存储到store_money数组中,对其进行排序即可。而代码中count和ans的作用,下文会给出。
sort(store_money, store_money + n1);
下面就是程序的关键代码了,由于前面我们已经将store_money数组进行了升序排序,根据Kruskal算法,我们需要从store_money[0]开始遍历数组,将每个位置的值与结构数组information中的money变量相匹配,如果值相等并且该位置还没有被遍历过,说明information数组在该位置是可选的。如果要确定该位置中的village1和village2中是否已经借助其它村庄联通,我们可以根据之前构建的二维数组map进行判断。相关代码如下:
for (int i = 0; i < n1; i++)
{
if (count == n - 1)
break;
for (int j = 0; j < n1; j++)
{
int h;
if (store_money[i] == information[j].money && information[j].judge==true)
{
for (h = 1; h < n + 1; h++)
if (map[information[j].village1][h] == 1 && map[information[j].village2][h] == 1)
break;
if (h == n + 1)
{
map[information[j].village1][information[j].village2] = 1;
map[information[j].village2][information[j].village1] = 1;
count++;
ans += store_money[i];
information[j].judge = false;
break;
}
}
}
}
其中的count变量所代表的是村庄之间已经修好的路,若count==n-1,则说明已经生成最小生成树;ans变量即为最终答案。当进入上述代码中第三个循环时,我们就开始通过二位数组map进行判断当前两个村庄是否已经通过其他村庄联通,因为前面说过,map中的值全部初始化为0,代表任意两个村庄之间没有路,当村庄之间有路时,就把相关位置的值赋值为1,如果第三个for循环中的if条件为真,则说明当前两个村庄已经通过其他村庄联通,不可再次选择。
接下来补充一下judge变量的作用:已经联通的村庄(无论是直接还是间接),在第二个for循环中不能在被遍历,因此,我们将road结构体中的judge初始化为1,表示可以被遍历,而当在两个村庄之间修完路后,将相应的judge赋值为0,从而避免了重复遍历。
当执行完第一个for循环后,所得到的ans即为答案。