这是一个最小生成树的题,我刚刚学完prim算法,那这个题来练练手,题目比较经典,没有坑,这里备忘录一下prim算法,主要是从一个自选节点开始(通常为一号)把所有与该节点相连的道路存在一个结构体数组里,结构体里有三个元素,起点终点和权(当然刚开始所有道路的起点都为自选节点编号),然后,从结构体数组里找出最小的路,将它与结构体数组里第一个结构体互换位置(该操作的实际意义在于把这个最小路保存下来,结构体数组里后面的元素为未保存不确定的路),然后将结构体数组里后面的路更新,把他们更新为能从整体(已保存的路径中),通往一个节点最小权的路,具体操作为:从刚刚找到的最短路的终点出发,到结构体数组里每一条路的终点的路中,找到比原有的在结构体数组中通往同一个终点且的路径短的路,并将其替换。所有的剩余路径更新完后,再从这些未保存的路径中找到最短路径,然后与这些未保存路径中的第一个路径交换位置(实际意义也同样是将改路径保存),以此类推,直到推出来n-1条路径,最后的路径权之和就是该题目答案。需要注意的是,在初始化的时候mapp二维数组里,自己通向自己的路径一定要初始化为0,以防止题目中有给出自己通向自己的路不为零这种恶心道路,其他道路初始化为无穷大来代表无道路通向两节点,至于题目中说到的没有通路的情况,我的处理方式为:在每次寻找最短路径的时候,如果找不到(也就是最短路径为无穷大)那么就直接结束循环,输出-1。
Problem Description
当前农村公路建设正如火如荼的展开,某乡镇政府决定实现村村通公路,工程师现有各个村落之间的原始道路统计数据表,表中列出了各村之间可以建设公路的若干条道路的成本,你的任务是根据给出的数据表,求使得每个村都有公路连通所需要的最低成本。
Input
连续多组数据输入,每组数据包括村落数目N(N <= 1000)和可供选择的道路数目M(M <= 3000),随后M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个村庄的编号和修建该道路的预算成本,村庄从1~N编号。
Output
输出使每个村庄都有公路连通所需要的最低成本,如果输入数据不能使所有村庄畅通,则输出-1,表示有些村庄之间没有路连通。
Sample Input
5 8 1 2 12 1 3 9 1 4 11 1 5 3 2 3 6 2 4 9 3 4 4 4 5 6
Sample Output
19
#include <iostream> #include <bits/stdc++.h> using namespace std; struct node { int qi,zhong,quan; }lu[3009]; int mapp[1009][1009]; int main() { int n,m,i,j,a,w,b,flag,mmin,J,sum; struct node temp; while(scanf("%d %d",&n,&m)!=EOF) { for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { if(i==j)mapp[i][j]=0; mapp[i][j]=99999999; } } for(i=1;i<=m;i++) { scanf("%d %d %d",&a,&b,&w); mapp[a][b]=w; mapp[b][a]=w; } for(i=2;i<=n;i++) { lu[i].quan=mapp[1][i]; lu[i].qi=1; lu[i].zhong=i; } for(i=2,flag=1;i<=n;i++) { mmin=99999999; for(j=i;j<=n;j++) { if(lu[j].quan<mmin) { mmin=lu[j].quan; J=j; } } if(mmin==99999999) { flag=0; break; } temp=lu[i]; lu[i]=lu[J]; lu[J]=temp; for(j=i+1;j<=n;j++) { if(mapp[lu[i].zhong][lu[j].zhong]<lu[j].quan) { lu[j].quan=mapp[lu[i].zhong][lu[j].zhong]; lu[j].qi=lu[i].zhong; } } } if(flag) { sum=0; for(i=2;i<=n;i++) { sum+=lu[i].quan; } printf("%d\n",sum); } else { printf("%d\n",-1); } } return 0; }