现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。
输入格式:
输入数据包括城镇数目正整数N(≤1000)和候选道路数目M(≤3N);随后的M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本。为简单起见,城镇从1到N编号。
输出格式:
输出村村通需要的最低成本。如果输入数据不足以保证畅通,则输出−1,表示需要建设更多公路。
输入样例:
6 15
1 2 5
1 3 3
1 4 7
1 5 4
1 6 2
2 3 4
2 4 6
2 5 2
2 6 6
3 4 6
3 5 1
3 6 1
4 5 10
4 6 8
5 6 3
输出样例:
12
代码如下:
#include<stdio.h>
#include<stdlib.h>
#define Max 1001
#define MaxInt 3000
int fcost=0;//最终成本
int flag=0;//是否连通的标记
struct edge{//当前点
int adjvex;//上一个点
int lowcost;//此点到未记录点的最短距离
}closedge[Max];
typedef struct{
int vexs[Max];//各村的信息
int arcs[Max][Max];//各村之间的路
int vexnum,arcnum;
}AMGraph;
void CreateAMGraph(AMGraph &G){//创建一连通图
int N,M;
scanf("%d%d",&N,&M);
G.vexnum=N;
G.arcnum=M;
for(int i=1;i<=N;i++){
G.vexs[i]=i;
}
for(int i=1;i<=N;i++){
for(int j=1;j<=N;j++){
if(i==j){
G.arcs[i][j]=0;
G.arcs[j][i]=0;
}
else{
G.arcs[i][j]=MaxInt;
G.arcs[j][i]=MaxInt;
//将不存在的路径设为最大值
}
}
}
for(int i=0;i<M;i++){
int x1,x2,x3;
scanf("%d%d%d",&x1,&x2,&x3);
G.arcs[x1][x2]=x3;
G.arcs[x2][x1]=x3;
}
}
int Min(AMGraph G){//找出当前点到各未标记点的最小距离并返回坐标
int minpath=MaxInt;
int minv=0;
for(int i=1;i<=G.vexnum;i++){
if(closedge[i].lowcost!=0){//已经记录的点无需再找,否则影响结果
if(closedge[i].lowcost<minpath){
minpath=closedge[i].lowcost; //此点的最小路径为表格中最小的点
minv=i;//记录该点
}
}
}
if(minv==0){//没找到最小点,说明不连通
flag=1;
}
fcost+=minpath;//把各步找到的最短路径都加起来
return minv;
}
void Prim(AMGraph G,int u){//普利姆算法求出最小生成树
closedge[u].lowcost=0;//标记第一个点
for(int i=1;i<=G.vexnum;i++){
if(i!=u){
closedge[i].adjvex=u;
closedge[i].lowcost=G.arcs[u][i];//起始点到各未标记点的路程
}
}
for(int i=1;i<G.vexnum;i++){
int x=Min(G);//从最近的点开始找下一个点
closedge[x].lowcost=0;//不要忘记给此点最短距离赋值为零
for(int j=1;j<G.vexnum;j++){
if(G.arcs[x][j]<closedge[j].lowcost){//更新最短距离
closedge[j].adjvex=G.vexs[x];//上一个点更新
closedge[j].lowcost=G.arcs[x][j];
}
}
}
}
int main(){
AMGraph G;
CreateAMGraph(G);
Prim(G,1);
if(flag==1)
printf("%d",-1);
else
printf("%d",fcost);
return 0;
}