博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
图论讲解(3)——最小生成树(基础)
阅读量:6991 次
发布时间:2019-06-27

本文共 2786 字,大约阅读时间需要 9 分钟。

关于这个东西,有的童鞋又要开始蒙了,最小生成树是个什么鬼?!

前面我们已经说过树是什么东西了,所谓最小生成树嘛,最小嘛,那就是所有生成的树中最小的那个呗!

太别扭了对吧?

好,我们来看看官方回答。

一个有 n 个结点的的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。最小生成树可以用(克鲁斯卡尔)算法或(普里姆)算法求出。

prim算法

Prim算法是通过先选取一个点,然后不断加入点的一个过程。
’初始化:V’={x},E’={},x是随便一个节点;
’重复下列操作,直到V’=V:
  ´在E集合当中选择最小的边<u,v>使得u∈V’但是v∉V’;
  ´V’加入节点v,E’加入<u,v>;
  ´(V’,E’)则为所求的最小生成树。

´我们可以对该算法里面的各个步骤分别考虑:
´初始化:V’={x},E’={},x是随便一个节点;
             这一步只需要随便选取一个点即可;
´重复下列操作,直到V’=V:
´在E集合当中选择最小的边<u,v>使得u∈V’但是v∉V’;
´V’加入节点v,E’加入<u,v>;
      对于上面的第二步,实际上我们只需要对于每一个点维护一个V’集合中的点到达该点的最短距离。
      然后每次扫描一遍数组找到我们所需要的v加入V’;
复杂度为O(N^2+M).
对于上面的第二步操作,我们实际上可以通过堆(优先队列)维护一个满足u∈V’但是v∉V’的边集,那么我们就能迅速取出满足要求的边;
然后当改变了V’的时候,我们就可以根据新加入的节点v对原有的堆进行删除和插入操作。
需要注意的是,当我们用优先队列实现的时候,我们需要将删除操作延迟。
复杂度为O((N+M)logN).
哔哔了这么多,我们直接来看看代码吧!
(当然先是一些板子)
 

#include<bits/stdc++.h>

using namespace std;
const int maxn=10010;
int n,m,edge[maxn][maxn];
int dis[maxn];
bool boo[maxn];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
edge[x][y]=edge[y][x]=z;
}
dis[1]=0;
boo[1]=true;
for(int i=2;i<=n;++i)
dis[i]=123456789;
for(int i=2;i<=n;++i)
if(edge[1][i])
dis[i]=min(dis[i],edge[1][i]);
int ans=0;
for (int i=1;i<=n-1;++i)
{
int maxd=0;
for(int j=1;j<=n;++j)
{
if(!boo[j])
if(maxd==0||dis[maxd]>dis[j])
maxd=j;
}
boo[maxd]=true;
ans+=dis[maxd];
for(int j=1;j<=n;++j)
{
if(!boo[j])
if(edge[maxd][j])
dis[j]=min(dis[j],edge[maxd][j]);
}
}
printf("%d\n",ans);
return 0;
}

Kruskal算法
Kruskal算法主要分为两步:
给所有边按照边权从小到大的顺序排序;
从小到大依次考虑每条边(u,v)(最开始没有任何的边):
如果u与v已经连通了,那么加入(u,v)后会出现环,不添加;
如果u与v没有连通,那么加入(u,v)使其连通。
然后,对于判断是否联通,我们可以通过并查集来维护。

是不是感觉k算法比p算法好理解啊(暂且先那么叫)

据徐大佬说k算法好像比p算法快,唉,如果让你写的话,是不是一定选择这种又快有好写还有好理解的代码啊。

反正让我写的的话,我一定会选择写k算法的,但是这仅限于裸地最小生成树的题。

对于有的题k算法是不如p算法的,甚至有的时候,你用k算法还不一定能做出来。

好了,废话不多说了,我们来看看代码吧。

 

#include 
using namespace std;const int maxn=100000+15;struct Edge{ int x,y,z;}edge[maxn];bool cmp(Edge a,Edge b){ return a.z

 

 

 

最小瓶颈生成树

有的童鞋看到这个就要抓狂了,这又是个什么鬼!!!

哎呀,不要着急,我们来具体看一看这个东西。

最小瓶颈生成树:在一个图中找出一棵树,使这棵树的最大权值最小。

给你一个这样的关系吧:最小生成树一定是最小瓶颈生成树,最小瓶颈生成树不一定是最小生成树。

最优比率生成树

给出一个图,每条边的权值是(a,b)的形式。求出一个生成树使得suma/sumb最小。
权值均为正值
´二分答案
´Suma/sumb>K
´Suma>Sumb*K,
´Sum(a-kb)>0
´一般的最大生成树
#include 
using namespace std;const int maxn=100000+15;struct Edge{ int x,y,a,b; Edge(int x=0,int y=0,int a=0,int b=0): x(x),y(y),a(a),b(b) {}}edge[maxn],edge2[maxn];int mst(){ return 0;}int change(int K){ for (int i=1;i<=m;i++) edge2[i]=Edge(edge[i].x,edge[i].y, edge[i].a-K*edge[i].b,0); return 0;}int main(){ scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { int x,y,a,b; scanf("%d%d%d%d",&x,&y,&a,&b); edge[i]=Edge(x,y,a,b); } int l=0,r=1000000,mid; while (l+1

 

转载于:https://www.cnblogs.com/z360/p/6853637.html

你可能感兴趣的文章
验证码识别技术研究
查看>>
WSDL文件生成java类
查看>>
我的友情链接
查看>>
CentOS7配置本地镜像及安装gluster服务
查看>>
android手势创建及识别
查看>>
弹了个框。。。不过不太好。 待解决
查看>>
keras 保存训练的最佳模型
查看>>
创业找投资,你要警惕的三种人---情商培养
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
大数据波分传输工程方案设计主要细节
查看>>
Z字形扫描(201412-2)
查看>>
如何确定Windows Server 2012中虚拟机的动态内存可用大小
查看>>
P2327 [SCOI2005]扫雷
查看>>
Hibernate基础实例
查看>>
索引设计规范
查看>>
python笔记4:计算输入时间为当年的第几天
查看>>
Linux 常用命令集合
查看>>
ARP的应用案例,测试ARP防火墙的主动防御功能;
查看>>
浅谈ipsec
查看>>