(ssl 1562)局域网#prim#

本文介绍了一种求解最小生成树(MST)的方法,并通过具体的算法实现来展示如何计算删去部分边后的总权重,以求得最小生成树。文章包含了一个C++实现的示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

nnn个点,mmm条边,求变成一个最小生成树所需要删去的边权和
这里写图片描述


分析

求的其实是最小生成树,删去的边的和就是答案。


代码

#include <cstdio>
#include <cctype>
#include <climits>
#include <cstring>
using namespace std;
int a[101][101],lowcost[101],v[101];
inline int in(){
	char x=getchar(); int ans=0;
	while (!isdigit(x)) x=getchar();
	while (isdigit(x)) ans=ans*10+x-48,x=getchar();
	return ans;
}
int main(){
	int ans=0,n,m,k,x1,y1,min,s=0; n=in(),m=in(); memset(a,127,sizeof(a)); memset(lowcost,127,sizeof(lowcost));
	for (int i=1;i<=m;i++) x1=in(),y1=in(),a[x1][y1]=in(),a[y1][x1]=a[x1][y1],ans+=a[x1][y1];
	for (int i=1;i<=n;i++) lowcost[i]=a[1][i];v[1]=1; 
	for (int i=1;i<=n-1;i++){
		min=INT_MAX;
		for (int j=1;j<=n;j++)
		if (lowcost[j]<min&&!v[j]){//最小值
			min=lowcost[j];
			k=j;
		}
		s+=min;
		v[k]=1;
		for (int j=1;j<=n;j++) if (a[k][j]<lowcost[j]) lowcost[j]=a[k][j];//更新最小值
	}
	printf("%d",ans-s); return 0;
}
### Prim算法及其贪心策略 #### 什么是Prim算法? Prim算法是一种用于求解图的最小生成树(Minimum Spanning Tree, MST)的经典算法。它通过逐步扩展已有的部分生成树来构建完整的最小生成树,每次选择连接当前生成树与其他未加入节点之间的最短边[^2]。 #### 贪心策略的核心思想 Prim算法基于贪心策略工作,其核心在于每一步的选择都是局部最优的,即每次都选择能够使总权重增加最少的边。这种“贪心”的决策方式最终可以证明会得到全局最优的结果——一棵具有最小权值和的生成树[^1]。 #### 算法的具体步骤 以下是Prim算法的主要操作流程: 1. **初始化** 开始时选定任意一个顶点作为起始点,并将其放入集合`S`中,其余所有顶点则位于另一个集合`V-S`中。 2. **迭代寻找最小边** 在每一次循环中,查找从集合`S`中的某个顶点出发到达集合`V-S`中任一顶点的所有可能路径上的最小权值边`(u,v)`,其中`u∈S`, `v∈V-S`。一旦找到这样的边,则把对应的顶点`v`移入集合`S`之中[^3]。 3. **更新邻接关系** 当新顶点被添加至集合`S`之后,重新评估剩余候选边上是否存在更优选项;如果存在更低成本的新连通可能性,则相应调整记录状态。 4. **终止条件** 此过程持续执行直至集合`S`覆盖整个顶点集`V`为止,此时所累积下来的全部选定点间连线共同组成了目标图的一棵最小生成树。 #### C++实现示例 下面给出了一种简单的C++语言版本的Prim算法实现方案: ```cpp #include <iostream> #include <vector> #include <limits> using namespace std; const int INF = numeric_limits<int>::max(); int prim(vector<vector<int>> &graph, int n) { vector<bool> inMST(n, false); // 是否已经在MST中 vector<int> key(n, INF); // 到达该结点所需的最小开销 vector<int> parent(n, -1); // 记录父节点 key[0] = 0; // 初始化第一个顶点为起点 for (int count = 0; count < n - 1; ++count){ int u = -1; // 寻找尚未加入MST且key值最小的顶点 for(int v=0; v<n; ++v){ if(!inMST[v] &&(u==-1 || key[v]<key[u])) u=v; } inMST[u]=true; // 更新相邻顶点的关键值 for(int v=0; v<n; ++v){ if(graph[u][v]!=INF && !inMST[v]){ if(key[v]>graph[u][v]){ key[v]=graph[u][v]; parent[v]=u; } } } } int result = 0; for(auto k : key) result +=k; return result; } // 测试函数 void test(){ int V =5 ; vector<vector<int>> graph(V ,vector<int>(V, INF)); graph[0][1]=2; graph[0][3]=6; graph[1][0]=2; graph[1][2]=3; graph[1][3]=8; graph[1][4]=5; graph[2][1]=3; graph[2][4]=7; graph[3][0]=6; graph[3][1]=8; graph[3][4]=9; graph[4][1]=5; graph[4][2]=7; graph[4][3]=9; cout << "Min Cost is "<< prim(graph,V)<< endl; } ``` 此代码片段定义了一个通用型的Prim算法框架并提供了一个小型测试案例展示如何调用上述功能计算给定无向加权图内的最小生成树总体耗费情况。 #### 应用场景分析 Prim算法广泛应用于网络设计领域,比如铺设电缆线路规划、公路建设布局优化等问题上都有实际意义。当面对大规模稀疏图时,通常推荐使用堆优先队列改进版Prim算法以提高效率性能表现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值