最小生成树--克鲁斯卡尔算法(Kruskal)
按照惯例,接下来是本篇目录:
$1 什么是最小生成树?
$2 什么是克鲁斯卡尔算法?
$3 克鲁斯卡尔算法的例题
摘要:本片讲的是最小生成树中的玄学算法--克鲁斯卡尔算法,然后就没有然后了。
$1 什么是最小生成树?
•定义:
先引入一个定理:N个点用N-1条边连接成一个联通块,形成的图形只可能是树,没有别的可能;
根据这个定理,我们定义:在一个有N个点的图中,选出N-1条边出来,连接所有N个点,这N-1条边的边权之和最小的方案;
•最小生成树之prim算法:
由于本蒟蒻还不会这个算法,所以暂时将这个算法放在这里,讲讲思路,代码实在不会打QAQ
算法思路:
1. 从图中选取一个节点作为起始节点(也是树的根节点),标记为已达;初始化所有未达节点到树的距离为到根节点的距离;
2. 从剩余未达节点中选取到树距离最短的节点i,标记为已达;更新未达节点到树的距离(如果节点到节点i的距离小于现距离,则更新);
3. 重复步骤2直到所有n个节点均为已达。
$2 什么是克鲁斯卡尔算法?
接下来是正题--克鲁斯卡尔算法
•算法思路:
(1)将所有边的边权从小到大依次排列,并且均标为未选;
(2)选择最小的未选边;
(3)如果该边与前面所选的边无法构成回路,则选中该边,并标为已选;如果该边与前面所选的边构成了回路,则不选该边,并标为已选;
(4)重复(2)(3),直到所有点之间都有边相连;
•举个栗子:
以下面这个图为例:

将各条边排序可得 3-4-5-6-6-7-8-9-12;
首先将最小的的边选上,即2--3,如图:

接下来,将第二条边选上,即1--2,如图:

第三条边:

第四条边是6,但是与前三条边构成了回路,不选它;
第五条边:

第六条边:

最后一条边:

•代码实现:
struct point
{
int x;//始边
int y;//终边
int v;//边的权值
};
point a[];
int fat[];
int n,i,j,x,m,tot,k;
int father(int x)//并查集中的查找
{
if(fat[x]!=x) fat[x]=father(fat[x]);
return fat[x];
} void unionn(int x,int y)//并查集中的合并
{
int fa=father(x);
int fb=father(y);
if(fa!=fb) fat[fa]=fb;
} int cmp(const point &a,const point &b)
{
if(a.v<b.v) return ;//对边的权值进行排序
else return ;
} int main()
{
cin>>n;
for(int i=;i<=n;++i)
for(int j=;j<=n;++j)
{
cin>>x;
if(x!=)
{
m++;
a[m].x=i;a[m].y=j;a[m].v=x;
}
}
for(int i=;i<=n;++i) fat[i]=i;
sort(a+,a+m+,cmp);
for(int i=;i<=m;++i)
{
if(father(a[i].x)!=father(a[i].y))
{
unionn(a[i].x,a[i].y);
tot+=a[i].v;
k++;
}//如果不能构成一个联通块,就将现在的这条边加入并查集
if(k==n-) break;//否则将现在的这条边撇开不管
}
cout<<tot;
return ;
}
神仙们想必都已经看出来了,克鲁斯卡尔算法用到了并查集的思想(不会并查集的神仙戳这儿),还是很好理解的。
$3 克鲁斯卡尔算法的例题
•有且只有的一个例题: 洛谷P1546 最短网络 Agri-Net:
题目背景
农民约翰被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场。当然,他需要你的帮助。
题目描述
约翰已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场。为了用最小的消费,他想铺设最短的光纤去连接所有的农场。
你将得到一份各农场之间连接费用的列表,你必须找出能连接所有农场并所用光纤最短的方案。每两个农场间的距离不会超过100000
输入输出格式
输入格式:
第一行: 农场的个数,N(3<=N<=100)。
第二行..结尾: 后来的行包含了一个N*N的矩阵,表示每个农场之间的距离。理论上,他们是N行,每行由N个用空格分隔的数组成,实际上,他们限制在80个字符,因此,某些行会紧接着另一些行。当然,对角线将会是0,因为不会有线路从第i个农场到它本身。
输出格式:
只有一个输出,其中包含连接到每个农场的光纤的最小长度。
输入输出样例
4
0 4 9 21
4 0 8 17
9 8 0 16
21 17 16 0
28
接下来是我懒得讲的代码(和上面一样)
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
struct point
{
int x;
int y;
int v;
};
point a[];
int fat[];
int n,i,j,x,m,tot,k;
int father(int x)
{
if(fat[x]!=x) fat[x]=father(fat[x]);
return fat[x];
} void unionn(int x,int y)
{
int fa=father(x);
int fb=father(y);
if(fa!=fb) fat[fa]=fb;
} int cmp(const point &a,const point &b)
{
if(a.v<b.v) return ;
else return ;
} int main()
{
cin>>n;
for(int i=;i<=n;++i)
for(int j=;j<=n;++j)
{
cin>>x;
if(x!=)
{
m++;
a[m].x=i;a[m].y=j;a[m].v=x;
}
}
for(int i=;i<=n;++i) fat[i]=i;
sort(a+,a+m+,cmp);
for(int i=;i<=m;++i)
{
if(father(a[i].x)!=father(a[i].y))
{
unionn(a[i].x,a[i].y);
tot+=a[i].v;
k++;
}
if(k==n-) break;
}
cout<<tot;
return ;
}
enddd~~
最小生成树--克鲁斯卡尔算法(Kruskal)的更多相关文章
- 贪心算法(Greedy Algorithm)之最小生成树 克鲁斯卡尔算法(Kruskal's algorithm)
克鲁斯卡尔算法(Kruskal's algorithm)是两个经典的最小生成树算法的较为简单理解的一个.这里面充分体现了贪心算法的精髓.大致的流程能够用一个图来表示.这里的图的选择借用了Wikiped ...
- 贪心算法(Greedy Algorithm)最小生成树 克鲁斯卡尔算法(Kruskal's algorithm)
克鲁斯卡尔算法(Kruskal's algorithm)它既是古典最低的一个简单的了解生成树算法. 这充分反映了这一点贪心算法的精髓.该方法可以通常的图被表示.图选择这里借用Wikipedia在.非常 ...
- 图->连通性->最小生成树(克鲁斯卡尔算法)
文字描述 上一篇博客介绍了最小生成树(普里姆算法),知道了普里姆算法求最小生成树的时间复杂度为n^2, 就是说复杂度与顶点数无关,而与弧的数量没有关系: 而用克鲁斯卡尔(Kruskal)算法求最小生成 ...
- 最小生成树-克鲁斯卡尔算法(kruskal's algorithm)实现
算法描述 克鲁斯卡尔算法是一种贪心算法,因为它每一步都挑选当前最轻的边而并不知道全局路径的情况. 算法最关键的一个步骤是要判断要加入mst的顶点是否会形成回路,我们可以利用并查集的技术来做. 并查集的 ...
- 最小生成树练习1(克鲁斯卡尔算法Kruskal)
今天刷一下水题练手入门,明天继续. poj1861 Network(最小生成树)新手入门题. 题意:输出连接方案中最长的单根网线长度(必须使这个值是所有方案中最小的),然后输出方案. 题解:本题没有直 ...
- 克鲁斯卡尔算法(Kruskal算法)求最小生成树
题目传送:https://loj.ac/p/10065 1.排序函数sort,任何一种排序算法都行,下面的示例代码中,我采用的是冒泡排序算法 2.寻源函数getRoot,寻找某一个点在并查集中的根,注 ...
- 最小生成树之Kruskal(克鲁斯卡尔)算法
学习最小生成树算法之前我们先来了解下下面这些概念: 树(Tree):如果一个无向连通图中不存在回路,则这种图称为树. 生成树 (Spanning Tree):无向连通图G的一个子图如果是一颗包含G的所 ...
- c/c++ 用克鲁斯卡尔(kruskal)算法构造最小生成树
c/c++ 用克鲁斯卡尔(kruskal)算法构造最小生成树 最小生成树(Minimum Cost Spanning Tree)的概念: 假设要在n个城市之间建立公路,则连通n个城市只需要n-1条线路 ...
- 最小生成树之克鲁斯卡尔(Kruskal)算法
学习最小生成树算法之前我们先来了解下 下面这些概念: 树(Tree):如果一个无向连通图中不存在回路,则这种图称为树. 生成树 (Spanning Tree):无向连通图G的一个子图如果是一颗包含G的 ...
随机推荐
- Java异步NIO框架Netty实现高性能高并发
原文地址:http://blog.csdn.net/opengl_es/article/details/40979371?utm_source=tuicool&utm_medium=refer ...
- 【原创】从Rest到Graphql
引言 开局两张图,内容全靠编- ok,如图所示,我在去年曾经写过一篇文章<闲侃前后端分离的必要性>.嗯,我知道肯定很多人没看过.所以我做一个总结,其实啰里八嗦了一篇文章,就是想说一下现在的 ...
- 【憩园】C#并发编程之异步编程(一)
写在前面 C#5.0中,对异步编程进行了一次革命性的重构,引入了async和await这两个关键字,使得开发人员在不需要深刻了解异步编程的底层原理,就可以写出十分优美而又代码量极少的代码.如果使用得当 ...
- day07(数据类型的相互转换 ,字符编码)
一,复习: ''' 1,深浅拷贝 ls = [1,'a',[10]] 值拷贝:直接赋值 ls1 = ls,ls中的任何值发生改变,ls1也随之发生改变 浅拷贝:通过copy()方法 ls2 = ls. ...
- pypinyin, jieba分词与Gensim
一 . pypinyin from pypinyin import lazy_pinyin, TONE, TONE2, TONE3 word = '孙悟空' print(lazy_pinyin(wor ...
- git 远程新建分支后,本地查看不到
使用以下命令同步 git remote # 列出所有远程主机git remote update origin --prune # 更新远程主机origin 整理分支git branch -r # 列出 ...
- LODOP中tfoot和tbody中间线连不起来
这种情况发生在使用ADD_PRINT_TABLE时,ADD_PRINT_TABLE是Lodop中专门用来输出table表格的语句,它有很多特点,比如该语句不切行(详细可参考查看本博客相关博文:LODO ...
- DNS预解析prefetch
前面的话 本文将详细介绍DNS预解析prefetch的主要内容 概述 DNS(Domain Name System, 域名系统),是域名和IP地址相互映射的一个分布式数据库.DNS 查询就是将域名转换 ...
- 特殊计数序列——Catalan数
Catalan数 前10项 \(1,1,2,5,14,42,132,429,1430,4862\) (注:从第\(0\)项起) 计算式 \(C_n=\frac{1}{n+1}\dbinom{2n}{n ...
- 【XSY3370】道路建设 最短路
题目大意 有一个完全图,边有边权. 对于每个 \(i\),求一棵生成树,使得( \(\sum_{j=1,j\neq i}^n\) \(j\) 到 \(i\) 的路径上边权最小值) 最小. \(n\le ...