最小生成树--克鲁斯卡尔算法(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的 ...
随机推荐
- flask轻量级框架入门
# -*- encoding: utf-8 -*- #导入Flask类, 导入重定向,url_for是简易寻址跳转, from flask import Flask,redirect,url_for, ...
- Android Studio自定义注释模板
一.自定义新建文件时生成的注释 setting->Editor->File and Code Templates->Includes->File Header,在这里输入自定义 ...
- PHP实现部分字符隐藏
/** * 隐藏部分字符串 * # 此方法多用于手机号码或身份证号.银行卡号的中间部分数字的隐藏 */ function func_substr_replace($str, $replacement ...
- git错集
2018年12月20日22:26:01 fatal:not a git repository ( or any of the parent directories ) : .git 这个错误出现在首次 ...
- 【问题解决方案】AttributeError: module 'pygal' has no attribute 'Worldmap'
<Python编程:从入门到实践>- 16章-16.2.5制作世界地图 import pygal 后报如标题的error 参考CSDN 解决:AttributeError: module ...
- AppiumDesktop录制脚本
AppiumDesktop启动页面: 启动AppiumDesktop以后点击该页面右上角的Start New Session按钮,就会启动一个新的会话窗口(如下图),在这个窗口我们需要配置一些Desi ...
- js检查身份证号是否正确
转的,比较完善的验证身份证号的代码 /* check(ID)验证身份证号码 返回值:0 : "是正确的身份证号" 1 : "身份证校验不符合求和模11=1这个等式&quo ...
- 2D-2D:对极几何 基础矩阵F 本质矩阵E 单应矩阵H
对极约束 \[ \boldsymbol{x}_{2}^{T} \boldsymbol{F} \boldsymbol{x}_{1}=\boldsymbol{0} \quad \hat{\boldsymb ...
- springdata 一对多配置
- 特殊计数序列——第二类斯特林(stirling)数
计算式 \[ S(n,m)=S(n-1,m-1)+mS(n,m) \] \(S(0,0)=1,S(i,0)=0(i>0)\) 组合意义 将\(n\)个不可分辨的小球放入\(m\)个不可分辨的盒子 ...