Road to every village (30 points) (prim algorithm)

In the statistical data table of the existing roads between villages, the cost of several roads that may be built into standard roads is listed, so that each village has the lowest cost required for road connectivity.

Input format: The
input data includes the positive integer N (≤1000) of the number of towns and the number of candidate roads M (≤3N); the following M rows correspond to M roads, and each row gives 3 positive integers, which are directly connected to the roads. The number of the two towns and the budgeted cost of the road reconstruction. For simplicity, the towns are numbered from 1 to N.

Output format:
output the minimum cost required by each village. If the input data is not enough to ensure smooth traffic, the output is −1, indicating that more roads need to be built.

Input sample:

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

Question idea:

1. From the original intent of the topic, in order to build a spanning tree with the smallest weight among many "points", obviously this is the definition of the minimum spanning tree. According to the prim algorithm, the minimum generation of components is required, and the shortest path can be output.
2. The code comments are very clear. If you don’t understand, you can comment on the private message. I will reply as soon as possible. I hope this article is helpful to you.

#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;
}

Guess you like

Origin blog.csdn.net/xdg15294969271/article/details/114238052