SCAU 18448 最小生成树 Prim算法

解答:

思路是先录入邻接矩阵,随机抽取一点开始(这里选取最后一个录入的边的起始点),把该点放入MST数组中,然后用双层循环遍历arr[MST[i]][j],j从1到节点数n,这样就遍历了所有已访问和未访问的节点中所有的边,将最小边的权值加到sum,并且把相连的节点放入MST数组 ,继续循环,得到最后的边权和。(这里没有说权值大于零,假定权值大于零)
 

#include<iostream>
using namespace std;
int main()
{
	int i,j,k=0,a,b,n,m,index,visited[2001]={0},MST[2001];
	//题目里面说节点数小于2000,但是开两千的数组会导致无法运行,经过测试,其实100大小的邻接矩阵就够了 
    long long arr[100][100]={0};
	long long max,sum=0,w;
	cin>>n>>m;
	
	//如果这是一个没有边的图,则最小生成树的边权和为0 
	if(m==0)
	{
		cout<<0;
		return 0;
	}
	
	//把权值录入邻接矩阵 
	for(i=0;i<m;i++)
	{
		cin>>a>>b>>w;
		//自环不录入,重边选小的录入 
		if(a!=b&&(arr[a][b]==0||w<arr[a][b])) 
		{
			//由于是无向图,所以邻接矩阵要录入两个方向的权值 
			arr[a][b]=w;
			arr[b][a]=w;
		}
	}
	
	//每次遍历一行
	visited[a]=1;//把a添加到已访问
	MST[k]=a;//已访问节点 
	k++;//k为已访问节点数 
	 
	 //在所有已访问的节点与未被访问的节点中找到一条最小的边 
	while(1)
	{
		 max=9223372036854775807; 
		for(i=0;i<k;i++)
		{
			for(j=1;j<=n;j++)
			{
				if(!visited[j]&&arr[MST[i]][j]!=0&&arr[MST[i]][j]<max)//如果j没有被访问过,且小于max 
				{
					max=arr[MST[i]][j];
					index=j;//保留j 
				}
			}
		}
		
		//循环结束后
		visited[index]=1;//把index添加到已访问
		MST[k]=index;//已访问节点 
		k++;//k为已访问节点数
		sum=sum+max;
		if(k==n) break;
	}
	 
	cout<<sum;
	
}

QA:

Q1:什么是Prim算法

A1:

  1. Prim 算法:

    • 初始化一个集合 MST,用于存储最小生成树的边。
    • 选择一个起始顶点 start
    • start 标记为已访问,并将其加入 MST
    • 重复以下步骤,直到所有顶点都被访问:
      • 在所有已访问的顶点和未访问的顶点之间的边中,选择权值最小的边 (u, v),其中 u 已访问,v 未访问。
      • 将顶点 v 标记为已访问,并将边 (u, v) 加入 MST
    • 遍历 MST,累加其中的边的权值,即为最小生成树的边权和。

Q2:如何处理自环,重边

A2:

自环不需要考虑,因为最小生成树是无环图。

假设ab两点之间有权值为3,4两条边,则在以a为起点选择最小边时,只有可能选择权值为3的那一条,所以我们在录入邻接矩阵的时候只需要录入小的权值即可。


题目:


18448 最小生成树
时间限制:1000MS  代码长度限制:10KB
提交次数:0 通过次数:0

题型: 编程题   语言: G++;GCC;VC
Description
给定结点数为n,边数为m的带权无向连通图G,所有结点编号为1,2,3....n。
求图G的最小生成树的边权和。


输入格式
第一行两个正整数n和m。n,m<=2000
之后的m行,每行三个正整数a,b,w,描述一条连接结点a和b,边权为w的边。1=<a,b<=n,w<=10^18。
注意可能存在重边和自环。


输出格式
一个整数表示图G的最小生成树的边权和(注意用长整型)。


输入样例
7 12
1 2 9
1 5 2
1 6 3
2 3 5
2 6 7
3 4 6
3 7 3
4 5 6
4 7 2
5 6 3
5 7 6
6 7 1


输出样例
16

作者 30002692

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现平衡二叉树的各种算法(如AVL树、红黑树等)可以应用在SCAU(South China Agricultural University,华南农业大学)的数据结构与算法课程中。这些算法的目标是确保二叉树的左右子树高度差不超过1,从而使树的高度保持相对较小的水平,提高插入、删除和查找等操作的效率。 一种常见的平衡二叉树算法是AVL树。实现AVL树的关键是通过旋转操作来保持树的平衡。在SCAU,可以使用多种编程语言(如C++、Java等)实现AVL树算法。插入新节点时,首先按照二叉查找树的方式找到合适的插入位置,然后通过不同的旋转操作调整树的平衡。具体的实现包括左旋、右旋、左右旋和右左旋等操作。 另一种常见的平衡二叉树算法是红黑树。SCAU可以使用编程语言(如C++、Java等)实现红黑树算法。红黑树通过使用辅助信息(即节点的颜色)来维持树的平衡。红黑树的插入操作包括节点的颜色变换和旋转操作。具体实现包括左旋、右旋、颜色变换等操作。 无论是AVL树还是红黑树,它们的实现都需要处理平衡调整,在插入或删除节点时通过旋转和颜色变换等操作来保持树的平衡。实现这些算法需要对平衡树的定义和性质有深入的理解,并具备编程技巧和数据结构基础。SCAU的学生在学习数据结构与算法课程时,可以通过理论学习和实践编程来掌握实现平衡二叉树的各种算法。除了课程的学习,还可以通过参考相关的教材、博客、论文等来加深对平衡二叉树算法实现的理解。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值