首页 > 其他分享 >最小生成树学习笔记

最小生成树学习笔记

时间:2023-08-25 11:13:05浏览次数:37  
标签:return int mst 最小 笔记 生成 prim 节点 dis

Prim算法

prim算法基本思想:基于点的解决方式

  1. 先随便选择一个点s作为起点,把其他所有点设为未添加节点,再设一dis数组,代表每个
    节点到最小生成树最近点的距离,易得一开始只有dis[s]=0,其他均为∞。
  2. 每轮找到dis值最小且未添加过的节点加入生成树中,且使用这个节点的邻边去更新它的邻
    点的dis值,如更新点为u,u->v有一条长度为x的边,则我们可以更新dis[v]为min(dis[v],x)。
  3. 重复执行操作②,直到所有点全部被添加。

伪代码

int prim(){
	d[1]=0; mst=0;
	for(each 除1以外的点v)d[v]=∞;
	for(i=1~n){
		找到未激活且d值最小的点u。
		if(找不到u) return -1;
		else mst+=d[u],u设为已激活;
		for (each u的后继点v)
			d[v]=min(d[v],G[u][v]);
	}
	return mst;
}

代码

struct point{
	int d,s;
	bool operator < (const point &a) const {
	    return s > a.s;
	}
};
vector<point>v[50100];
int prim(){
	int ans=0;
	for(int i=1;i<=n;i++)dis[i]=1e9;
	priority_queue<point>q;
	dis[1]=0;
	q.push(point{1,0});
	while(!q.empty()&&c<n){
		int u=q.top().d;
		q.pop();
		if(!b[u]){
			c++;
			b[u]=1;
			for(int i=0;i<v[u].size();i++){
				int d=v[u][i].d,s=v[u][i].s;
				//cout<<d<<" "<<s<<' '<<dis[d]<<endl;
				if(!b[d]&&dis[d]>s){
					dis[d]=s;
					q.push(point{d,dis[d]});
				}
			}
			ans+=dis[u];
		}
	}
	//cout<<c<<endl;
	if(c==n)return ans;
	else return -1;
}

Kruskal

考虑一种贪心的思想:从小到大加边

  1. 初始化。将所有边都按权值从小到大排序,将每个节点集合号都初始化为自身编号。

  2. 按排序后的顺序选择权值最小的边 \((u,v)\)。

  3. 如果节点 \(u\) 和 \(v\) 属于两个不同的连通分支,则将边 \((u,v)\) 加入边集 \(TE\) 中,并将两个连通分支合并。

  4. 如果选取的边数小于 \(n-1\) ,则转向步骤2,否则算法结束。

图解

image

结果:

image

伪代码

int kruskal(){
	给边集按权值w排序。
	mst=0;
	for(each 边集中的边(u,v,w)){
		if(u和v不在一个集合中){
			mst+=w;
			将u和v连起来;
		if(所有点在一个集合中)
			return mst;
		}
	}
	return -1;
}

代码

int fa[100001],n,k,m,ans,cnt;
struct edge{
	int u,v,w;
}v[201000];
bool cmp(edge x,edge y){
    return x.w<y.w;
}
int find(int x){
    while(x!=fa[x])x=fa[x]=fa[fa[x]];
    return x;
}
int kruskal(){
    sort(v,v+m,cmp);
	for(int i=0;i<=n;i++)fa[i]=i;
    for(int i=0;i<m;i++){
        int fu=find(v[i].u),fv=find(v[i].v);
        if(fu==fv)continue;
        ans+=v[i].w;
        fa[fv]=fu;
		cnt++;
        if(cnt==n-1)return ans;
    }
    return -1;
}

复杂度

kruskal:\(O(mlogm)\)
prim:\(O(mlogn)\)

标签:return,int,mst,最小,笔记,生成,prim,节点,dis
From: https://www.cnblogs.com/ccr-note/p/MST.html

相关文章

  • 并查集学习笔记
    并查集的定义并查集是一种树型的数据结构,用于处理一些不相交集合(disjointsets)的合并及查询问题。常常在使用中以森林来表示。——百度百科并查集,顾名思义,支持以下两种操作操作:并(Union):把两个不相交的集合合并为一个集合。查(Find):查询两个元素是否在同一个集合中。并......
  • 字典树学习笔记
    字典树字典树(Trie)简介又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比......
  • 微调llama2模型教程:创建自己的Python代码生成器
    本文将演示如何使用PEFT、QLoRa和Huggingface对新的lama-2进行微调,生成自己的代码生成器。所以本文将重点展示如何定制自己的llama2,进行快速训练,以完成特定任务。 https://avoid.overfit.cn/post/9794c9eef1df4e55adf514b3d727ee3b......
  • IDEA 生成的 JAVA 接口允许跨域访问的配置
    1.新建一个基类,在类上方添加 @CrossOrigin属性importorg.springframework.web.bind.annotation.CrossOrigin;@CrossOriginpublicclassBaseController{}2.在其他controller中继承这个基类,其他接口就可以跨域访问了publicclassElseControllerextendsBaseContr......
  • C# 使用 PaddleOCRSharp 识别 图片中的文字、 使用QRCoder生成二维码
    使用PaddleOCRSharp识别图片中的文字  在只用PaddleOCRSharp之前用过另外一种识别:Tesseract。它识别速度是非常快的,但是准确率堪忧,而且使用的时候需要区分语言,这里权当一些经验交流,不是说Tesseract不好。PaddleOCRSharp资料汇总:开源工具开发者博客:https://www.cnblogs.com/ra......
  • VisionPro 如何通过向导生成项目应用程序
    最终结果Job1:识别二维码Job2:变形匹配......
  • 代码随想录第二天|977.有序数组的平方;209.长度最小的子数组;59.螺旋矩阵II,总结
    今天的这三道题每道题对我来说都不简单,有序数组的平方和长度最小的子数组这两道题还能用暴力求解,螺旋矩阵看着简单却没有思路,磨了半小时还是决定直接看讲解有序数组平方和用的双指针的思想,代码如下:1classSolution{2public:3vector<int>sortedSquares(vector<int......
  • 《深入理解Java虚拟机》读书笔记:方法调用
      方法调用并不等同于方法执行,方法调用阶段唯一的任务就是确定被调用方法的版本(即调用哪一个方法),暂时还不涉及方法内部的具体运行过程。在程序运行时,进行方法调用是最普遍、最频繁的操作,但前面已经讲过,Class文件的编译过程中不包含传统编译中的连接步骤,一切方法调用在Class文件......
  • 赵老师 计数原理 课程笔记
    计数原理分类加法计数原理与分步乘法计数原理分类加法计数原理引例题干用一个大写的英文字母或一个阿拉伯数字给教室里的一个座位编号,总共能编出多少种不同的号码?解决因为英文字母共有\(26\)个,阿拉伯数字共有\(10\)个,所以总共可以编出\(26+10=36\)种不同的号......
  • Programming abstractions in C阅读笔记:p127-p129
    《ProgrammingAbstractionsInC》学习第51天,p127-p129,总结如下:一、技术总结1.stringlibrary掌握常用函数如strlen,strcpy用法。2.bufferoverflow(缓冲区溢出)(1)什么是buffer?p129,Arraysthatarepreallocatedandlateruseasarepositoryfordatacalledbuffers......