通过Kruskal算法与二维数组实现最小生成树

	已知有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即为答案。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值