prim算法机试模板|C++

prim算法和前面我发的kruskal算法都是求最小生成树的算法,kruskal我总结是暴力解法,prim的话就没有kruskal那么简单暴力,prim是靠着把结点分成两个集合,一个是已经加进来的结点集合,一个是未进来的结点集合,然后依次遍历。

要理解两层循环的意思:
第一层循环:一共要加入N个点,所以循环N次
第二层循环:遍历N个结点,查看是不是未加入的结点,并且比较是不是这个距离比较小。

//prim算法:把结点分成两个集合,一个访问过,一个未访问过,然后两次遍历
#include <stdio.h>
#include <iostream>
#pragma warning(disable:4996);
using namespace std;

int N, M;//N个结点,M条边
const int maxn = 5010;
const int INF = 0x3f3f3f3f;
bool visit[maxn];
int Adj[maxn][maxn];
int Dis[maxn];

int prim()
{
	fill(Dis, Dis + maxn, INF);
	int ans = 0;
	//首先初始化
	Dis[1] = 0;
	for (int i = 2; i <= N; i++)
	{
		Dis[i] = Adj[1][i];
	}

	for (int i = 0; i < N; i++)
	{
		int t = -1;
		for (int j = 1; j <= N; j++)
		{
			if (visit[j] == false && (t == -1 || Dis[j] < Dis[t]))
			{
				t = j;
			}
		}
		if (Dis[t] == INF)
		{
			return INF;
		}
		else
		{
			ans += Dis[t];
		}
		visit[t] = true;
		//更新
		for (int k = 1; k <= N; k++)
		{
			if (Adj[t][k] < Dis[k])
			{
				Dis[k] = Adj[t][k];
			}
		}
	}
	return ans;
}

int main()
{
	scanf("%d %d", &N, &M);
	fill(visit, visit + maxn, false);
	fill(Adj[0], Adj[0] + maxn * maxn, INF);
	//m条边 和路径
	for (int i = 0; i < M; i++)
	{
		int node1, node2,w;
		scanf("%d %d %d", &node1, &node2, &w);
		Adj[node1][node2] = Adj[node2][node1] = min(w, Adj[node1][node2]);
	}
	int ans = prim();
	if (ans == INF) {
		printf("orz");
	}
	else {
		printf("%d\n", ans);
	}
	
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
抱歉,我无法提供流程图。但是,我可以为您提供Prim算法C++代码示例和简要解释。 以下是Prim算法C++代码示例: ```cpp #include <iostream> #include <climits> using namespace std; #define V 5 int minKey(int key[], bool mstSet[]) { int min = INT_MAX, min_index; for (int v = 0; v < V; v++) { if (mstSet[v] == false && key[v] < min) { min = key[v]; min_index = v; } } return min_index; } void printMST(int parent[], int graph[V][V]) { cout << "Edge \tWeight\n"; for (int i = 1; i < V; i++) { cout << parent[i] << " - " << i << "\t" << graph[i][parent[i]] << endl; } } void primMST(int graph[V][V]) { int parent[V]; int key[V]; bool mstSet[V]; for (int i = 0; i < V; i++) { key[i] = INT_MAX; mstSet[i] = false; } key[0] = 0; parent[0] = -1; for (int count = 0; count < V - 1; count++) { int u = minKey(key, mstSet); mstSet[u] = true; for (int v = 0; v < V; v++) { if (graph[u][v] && mstSet[v] == false && graph[u][v] < key[v]) { parent[v] = u; key[v] = graph[u][v]; } } } printMST(parent, graph); } int main() { int graph[V][V] = {{0, 2, 0, 6, 0}, {2, 0, 3, 8, 5}, {0, 3, 0, 0, 7}, {6, 8, 0, 0, 9}, {0, 5, 7, 9, 0}}; primMST(graph); return 0; } ``` 这段代码实现了Prim算法来构造最小生成树。它使用了一个辅助函数`minKey`来找到具有最小键值的顶点,然后将其添加到最小生成树中。`printMST`函数用于打印最小生成树的边和权重。`primMST`函数是主要的Prim算法函数,它初始化关键数组和最小生成树集合,并在每次循环中选择下一个顶点并更新关键数组。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值