C 最小生成树 + Prim算法 08-图7 公路村村通 (30分)

08-图7 公路村村通 (30分)

现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。

输入格式:
输入数据包括城镇数目正整数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

解题
由给定结点和边,构造最小生成树;
输出最小生成树边权值的总和;
关键点:最小生成树的构造方法

Prim算法

设置一个点为第一棵树,此点dist为0;
更新此点直接相连结点的dist,为边长;
进入循环,遍历每一个结点的dist,当其不为0(表示不在树内)且最小时,收入树内,并加上这条边的边长,同时记录树种已有结点的结点个数;
判断:
当循环跳出时——说明没有不在树内且与树右边相连的结点了,若此时树内结点与总结点数量不同,说明该图不连通,不存在最小生成树;
若连通,输出总路径长度即可;

1.输入函数

#include<iostream>
using namespace std;
#define inf 0x3f3f3f3f
#define MAXNUM 1010
int N,M;
int Graph[MAXNUM][MAXNUM];

void input()
{
	fill(Graph[0],Graph[0]+MAXNUM*MAXNUM,inf); //一定要记得初始化 
	cin>>N>>M;
	for(int i=0;i<M;i++)     //读入15条边 
	{
		int a,b,weight;
		cin>>a>>b>>weight;
		Graph[a][b]=weight;
		Graph[b][a]=weight;
	}
}

2.Prim函数

int prim()     
{
	int dist[MAXNUM];
	int totalweight=0;
	int Vcount=0;
	//从1出发
	fill(dist,dist+MAXNUM,inf);      //初始化dist
	dist[1]=0;    // 挑一个结点先入,这里选择编号为1的结点
	Vcount++;      
	for(int i=1;i<=N;i++)      //更新第一个结点周围的dist 
		if(dist[1]+Graph[1][i]<dist[i])
			dist[i]=Graph[1][i];

	
	while(1)
	{	int Min=inf;
		int V=-1;
		for(int i=1;i<=N;i++)                  //在dist中找最小值
			if(dist[i]!=0&&dist[i]<Min)
			{
				Min=dist[i];
				V=i;
			}

		
		if(V==-1) break;
		totalweight+=dist[V];  //加上路径长度 
		dist[V]=0;             //将结点加入树内 
		Vcount++;              //记录结点数 
		
		for(int i=1;i<=N;i++)
			if(dist[V]+Graph[V][i]<dist[i])	//只更新结点为0的周围距离 
				dist[i]=Graph[V][i];
	}
	if (Vcount<N) totalweight=-1;
	return totalweight;
}

3.main函数

int main()
{
	input();
	int result=prim();
	cout<<result;
 }
发布了105 篇原创文章 · 获赞 6 · 访问量 4950

猜你喜欢

转载自blog.csdn.net/BLUEsang/article/details/105511806