浅记 最小生成树prim kruskal

prim 加点

求最小生成树的一种贪心算法

把有权连通图中的所有点,分入两个集合A,B

A是已被记入最小生成树中的点,B是没有被记入的

每一次操作,在A中找到 i,在B中找到 j,使以i 与 j为端点的边的权值最小

开始时定义一点为源头,从这个源头逐渐蔓延

过程 从任意一个点开始,直至所有点相连

时间 复杂度 O(n^2)

void prim() {
	tot=0,vis[s]=1;
	for(ri i=1; i<=n; ++i) dis[i]=f[s][i];
	for(ri i=1; i<=n; ++i) {
		minn=maxx,k=0;
		for(ri j=1; j<=n; ++j) {
			if(!vis[j]&&dis[j]<minn) minn=dis[j],k=j;
			tot+=minn,vis[k]=1;
			for(ri j=1; j<=n; ++j) if(dis[j]>f[k][j]) dis[j]=f[k][j]; } } }

kruskal 加边

求最小生成树的一种贪心算法

主线是按从小到大的排序来选择边

暗线是一个必要条件:要成树

也就是,原来的树加上这次操作的边不成环,且使 n-1 条边连接 n 个点,不漏点

过程 从最小边开始,直至已操作 n-1 条

时间 复杂度O(ElogE)

void kruskal() {
	for(ri i=1; i<=n; ++i) fa[i]=i;//按点循环 
	sort(a+1,a+1+n,cmp);
	for(ri i=1; i<=m; ++i) {//按边循环 
		if(k==n-1) break;//n个点,用n-1条边相连  
		int r1=find(a[i].x),r2=find(a[i].y);
		if(r1!=r2) fa[r2]=r1,++k,tot+=a[i].w; } }//长边接短边

prim 和 kruskal

类似于 练习时一道一道写 ( prim ) 和挑着写 ( kruskal )

挑着写灵巧方便省力,但遇到练习过多时,挑不过来,就不适用

一道一道写就显得严丝合缝一些

同理

kruskal 简单易操作,但搞不定节点过多的题

prim 则格外适用于数据量大、连通图边数多的问题

另外 prim也便于解决近点输出的问题


over

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值