公路村村通 (30 分)(prim算法)

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

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

题目思路:

1.从题目的本意来看为了在很多“点”之间建立一个权值最小的生成树,显然这就是最小生成树的定义,按照prim算法构件最小生成,把最短路径输出即可。
2.代码的注释写的很清楚,有不懂的可以评论私信,我会尽快回复,希望这篇文章对你有所帮助。

#include<iostream>
#include<algorithm>
const int MAXN = 1005;
const int INF = 0x3f3f3f3f;
using namespace std;

int Graph[1005][1005];
int d[1005];
bool Visited[1005] = {
    
     false };
int n, m;
int Prim();
int FindMin();
int main()
{
    
    
	int a, b, c;
	cin >> n >> m;
	fill(Graph[0], Graph[0] + 1005*1005, INF);	//初始化图
	while (m--)			//建图
	{
    
    
		cin >> a >> b >> c;
		Graph[a][b] = Graph[b][a] = c;	//无向图
	}

	int ans = Prim();
	cout << ans;

	return 0;
}
int Prim()
{
    
    
	fill(d, d + MAXN, INF);		//将d数组初始化
	d[1] = 0;					//将第一个顶点作为起点,用其他点最终答案都一样,只是生成的图形状不一样,但权值都一样
	int ans = 0;				//记录权值之和

	for (int i = 1; i <= n; i++)	//注意这里的下标,数字下标,且从0开始。
	{
    
    
		int u = FindMin();	//找到未访问的d[]中最小的权值
		if (u == -1) return -1; //如果找不到小于INF的d[u], 则说明剩下的点和集合S不连通
		Visited[u] = true;
		ans += d[u];			//找到最小的权值路累加起来。

		for (int v = 1; v <= n; v++)
			if (!Visited[v] && Graph[u][v] != INF && Graph[u][v] < d[v])//如果没有访问过,而且u能到达v,以u作为中介能找到更短的边
				d[v] = Graph[u][v];		//更新d数组
	}

	return ans;
}
int FindMin()
{
    
    
	int ret = -1;
	int MIN = INF;
	for (int i = 1; i <= n; i++)
	{
    
    
		if (!Visited[i] && d[i] < MIN)
		{
    
    
			ret = i;
			MIN = d[i];
		}
	}
	return ret;
}

猜你喜欢

转载自blog.csdn.net/xdg15294969271/article/details/114238052