Kruskal算法
来自"NOCOW"
跳转到: 导航, 搜索
目录 [隐藏]
1 预备知识
2 基本思想
3 PASCAL代码
4 C语言代码
5 优化
6 算法实例
6.1 VOJP1045
[编辑] 预备知识
排序算法(必须)
并查集(非必须)
[编辑] 基本思想
假设WN=(V,{E})是一个含有n个顶点的连通网,则按照克鲁斯卡尔算法构造最小生成树的过程为:先构造一个只含n个顶点,而边集为空的子图,若将该子图中各个顶点看成是各棵树上的根结点,则它是一个含有n棵树的一个森林。之后,从网的边集E中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,也就是说,将这两个顶点分别所在的两棵树合成一棵树;反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。依次类推,直至森林中只有一棵树,也即子图中含有n-1条边为止。</p>
[编辑] PASCAL代码
Procedure kruskal(V,E);
begin
sort(E,1,m);//将边按照权值排序
for t:=1 to m do begin
if getfather(edge[t].u)<>getfather(edge[t].v) then begin //利用并查集判断两个顶点是否在同一集合内
tot:=tot+edge[t].data;//计算权值和
union(edge[t].u,edge[t].v);//合并顶点
inc(k);//合并次数
end;
end;
if k=n-1 then 形成了一棵最小生成树
else 不存在这样的最小生成树;
end;[编辑] C语言代码
void kruskal(Vertex V,Edge E)
{
sort(E,1,m);//将边按照权值排序
for (t=1;t<=m;t++) {
if( getfather(edge[t].u)!=getfather(edge[t].v) ) { //利用并查集判断两个顶点是否在同一集合内
tot=tot+edge[t].data;//计算权值和
Union(edge[t].u,edge[t].v);//合并顶点
k++;//合并次数
}
}
if( k==n-1 ) 形成了一棵最小生成树;
else 不存在这样的最小生成树;
}[编辑] 优化
在判断两个顶点是否在同一集合内时可用并查集
代码可以如下
procedure union(x,y:longint);
begin
if r[y]<r[x] then
begin
y:=y xor x;
x:=y xor x;
y:=y xor x
end;//Matrix67式交换
//扯淡,谁说这是matrix67发明的 --[[User:Cosechy|Cosechy]] 17:00 2008年11月13日 (CST)
//问题在于,我们都是从M67大牛那里学来的——OiBLtx
//不管怎么交换,请你们保持代码整洁。--Yinger650
p[x]:=y;
if r[y]=r[x] then inc(r[x]);
end;
function find(x:longint):longint;
begin
if x<>p[x] then p[x]:=find(p[x]);
exit(p[x]);
end;
function clear:boolean;
var
i,t:longint;
begin
clear:=true;
t:=find(1);
for i:=2 to m do if find(i)<>t then exit(false);
end;
procedure solve;
var
i,k:longint;
begin
for i:=1 to n do
begin
if clear then exit;
if find(a[i].f)<>find(a[i].t) then
begin
inc(ans,a[i].c);
union(find(a[i].f),find(a[i].t));
end;
end;
end;//注: 使用前请排序[编辑] 算法实例
[编辑] VOJP1045
题目简述:
1、输入:
第一行一个正实数S:要求最小生成树中所有边的长度不大于s
第二行一个正整数n:有n个结点
接下来一共有m行,第i行有两个整数xi,yi和一个实数si,表示点xi和点yi间有一条边,边的长度为si。
输入保证xi不等于yi,两个点之间不会有两条边。
2、输出:
若存在这样的最小生成树,则输出(其中<X>代表最少的电缆线长度,保留两位小数):
Need <X> miles of cable
否则输出:
Impossible
代码框架:
type edge=record
u,v:longint;
end;
var e:array[1..max] of edge;
rank,p,node:array[1..max] of longint;
w:array[1..max] of real;//w为边的长度(即耗费)
s,cost:real;
es,n:longint; //es为总的边数
procedure swap(n1,n2:longint);
var t:longint;
begin
t:=node[n1]; node[n1]:=node[n2]; node[n2]:=t;
end;
procedure init;
var x,y:longint;
begin
readln(s);
readln(n); es:=0;
while not(eof) do begin
read(x,y);
p[x]:=x; p[y]:=y; //并查集初始化
inc(es);
if x<y then begin
e[es].u:=x; e[es].v:=y;
end else begin
e[es].u:=y; e[es].v:=x;
end;
readln(w[es]);
node[es]:=es;
end;
qsort(1,es);//快排,node[i]为边长第i小的边的序号。程序略
end;
procedure union(x,y:longint);//并查集:合并x,y所在集合
begin
if rank[x]>rank[y] then
p[y]:=x else begin
p[x]:=y;
if rank[x]=rank[y] then inc(rank[y]);
end;
end;
function findset(x:longint):longint;//并查集:查找x所在集合的代表元素
begin
if x<>p[x] then p[x]:=findset(p[x]);
exit(p[x]);
end;
procedure main;
var i:longint;
begin
for i:=1 to n do
if p[i]=0 then begin//若点i为孤立点则无解
writeln('Impossible');
halt;
end;
for i:=1 to es do
if findset(e[node[i]].u)<>findset(e[node[i]].v) then begin
union(findset(e[node[i]].u),findset(e[node[i]].v));
inc(cost,w[node[i]]);
end;
end;
begin
init;
main;
if cost<=s then writeln('Need ',cost:0:2,' miles of cable')
else writeln('Impossible');
end.
分享到:
相关推荐
Kruskal算法是一种用于寻找图的最小生成树的经典算法,由Joseph Kruskal在1956年提出。它的核心思想是贪心策略,即在每次选择边时,优先选择权重最小的边,同时避免形成环路。在这个过程中,我们可以使用并查集...
代码 最小生成树kruskal算法离散型优化问题代码代码 最小生成树kruskal算法离散型优化问题代码代码 最小生成树kruskal算法离散型优化问题代码代码 最小生成树kruskal算法离散型优化问题代码代码 最小生成树kruskal...
在这个问题中,Prim算法和Kruskal算法是两种常用的方法。 1. Prim算法: Prim算法是一种贪心策略,它从一个起始顶点开始,逐步添加边,每次添加一条与已选择顶点集形成最小权重边的新边。这个过程不断进行,直到...
### 使用Prim和Kruskal算法构建最小生成树 在图论中,最小生成树(Minimum Spanning Tree, MST)是一个非常重要的概念。对于一个连通的无向图来说,如果存在一个子图,它包含原图的所有顶点,并且这些顶点通过边...
Kruskal算法python实现,包括无向图的绘制,需要自己在桌面上先建关于无向图的TXT
本文将详细介绍两种经典算法来解决最小生成树问题:Prim算法和Kruskal算法,并以C语言实现为例进行讲解。 ### Prim算法 Prim算法是一种贪心算法,其基本思想是从一个初始节点开始,逐步添加最短的边,直到连接到...
数据结构课程设计报告最小生成树Kruskal算法 数据结构课程设计报告中,我们将使用Kruskal算法来生成最小生成树,该算法是图论中的一种经典算法,能够在给定的图中找到最小生成树。下面,我们将对Kruskal算法的实现...
最小生成树Kruskal算法 标题:最小生成树Kruskal算法 描述:java编写的最小生成树Kruskal算法,参考:算法设计和分析 标签:最小生成树 Kruskal算法 JAVA 知识点概述: 1. 最小生成树(Minimum Spanning Tree)...
Matlab版Prim Kruskal算法实现文档 一、Prim算法 Prim算法是图论中的一种常用算法,用于求解最小生成树问题。其基本思想是以局部最优化谋求全局的最优化。该算法的实现步骤如下: 1. 设G=(V,E)是一个无向连通网...
### 数学建模中的Kruskal算法:构建最小生成树 #### 一、Kruskal算法简介 Kruskal算法是解决最小生成树问题的一种高效算法,在数学建模与计算机科学领域有着广泛的应用。该算法由Joseph Kruskal在1956年提出,其...
Prim算法和Kruskal算法的Matlab实现 Prim算法和Kruskal算法是两种常用的最小生成树算法,它们在计算机仿真和软件开发中有广泛的应用。本文将对这两种算法进行深入的分析和比较,并使用Matlab实现它们的代码实现。 ...
数据结构课程设计中的Kruskal算法是图论领域的一个重要概念,主要应用于寻找图的最小生成树。在本课程设计中,我们利用MFSET(即Disjoint Set,也称为并查集)的数据结构来实现这一算法。MFSET是一种高效处理集合...
### 最小生成树Kruskal算法详解 #### 算法背景与定义 最小生成树(Minimum Spanning Tree,简称MST)是图论中的一个经典问题,涉及到在一个加权图中寻找一棵包含所有顶点的子图,使得这棵子图的总权重最小。在实际...
Kruskal算法是一种经典的图论算法,用于寻找加权无向图中的最小生成树。最小生成树是指在不增加边的权重的情况下,连接所有顶点的树形子图。Kruskal算法的主要思想是按边的权重递增顺序选择边,并在选择过程中避免...
Kruskal算法同样是一种贪心策略,它按照边的权重从小到大排序,依次选择边,但避免形成环路。具体步骤如下: 1. **边的排序**:将图中的所有边按照权重进行升序排序。 2. **并查集初始化**:建立一个表示顶点关系的...
Prim算法和Kruskal算法是两种常用的求解最小生成树的方法,它们各有特点和适用场景。 1. **Prim算法**: Prim算法是从一个顶点开始,逐步添加边来构建最小生成树。它每次选择与当前树连接且权重最小的边,直到所有...