Kruskal 算法是一个求最小生成树的算法,即求最小的开销等

算法可以这样,要求得最小生成树,那么n个节点只能包括n-1条边

所以我们应该转换为寻找这最短的n-1条边,因此,可以先对所有的

边进行从小到大排序,每次取出一条边来进行试探,看是否够成环,

如果不构成环,那么肯定是最短的路径了,因为每次都是取最小

的边来试探,最终可以求得最小的生成树代价和。

/*
Filename:kruskal.cpp
Author: xiaobing
E-mail: xiaobingzhang29@gmail.com
Date: 2013-08-31
*/
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<cstdlib>
#include<list>
#include<set>
#include<vector>
#define N 100
#define INF 1000000
using namespace std; /*
Kruskal 算法是一个求最小生成树的算法,即求最小的开销等
算法可以这样,要求得最小生成树,那么n个节点只能包括n-1条边
所以我们应该转换为寻找这最短的n-1条边,因此,可以先对所有的
边进行从小到大排序,每次取出一条边来进行试探,看是否够成环,
如果不构成环,那么肯定是最短的路径了,因为每次都是取最小
的边来试探,最终可以求得最小的生成树代价和。
用到的数据结构:
struct edge 表示一条边,包括两个端点及其代价
edge graph[N] 表示有N条边组成的图
int father[N] 表示每个点的最上层的根节点
解释:因为这里需要判断是否形成环路,可以这样,每添加一条
边,看两个点是否在已经添加进去的边的点集中,若对需要添加
的这条边,发现两个点都在之前的那个集合中,这一定会形成回
路,所以,这里设置一个数组father[N],起初时,每个值为-1,代
表每个点的根节点都没有(因为没有添加一条边进去),当添加一条
边后,如果他们的根节点不同,则设置大的那个点的父节点为小
的那个点,如x > y 则 father[x] = y,这样每个点都只有一个根,
或者没有根,为-1,所以对添加进的节点,都可以查出他的根,然后
做比较,都相同,说明已位于添加进的节点中了,否则把该边添加
进去。 */ //定义一条边
struct edge{
int u; //起始点
int v; //目的点
int cost; //两点之间的代价
}; //这是一个对块数排序算法调用的一个比较函数
bool cmp(const edge &a, const edge &b){
return a.cost < b.cost;
} //查找一个节点的根节点
int findFather(int father[], int x){
//如果他的父节点不为-1,则应该递归,直到找到其父节点
if(father[x] != -1){
//将沿途的所有节点都指向同一个根节点
return father[x] = findFather(father, father[x]);
} //若为-1,则该点就是根
return x;
} //添加一条边
bool unionEdge(int father[], int x, int y){
//找到一条边的两个端点的根节点
x = findFather(father, x);
y = findFather(father, y); //根节点相同,说明已经加入了,再加入该边
//则会形成回路,该边舍弃,返回fasle
if(x == y){
return false;
} //若不同,让大的节点的根节点指向小的节点
if(x > y) father[x] = y;
if(x < y) father[y] = x; //该边可以加入,返回true
return true;
} int main(){
edge graph[N]; //定义了一个包含N条边的图
int father[N]; //定义了一个包含N个节点的根节点
int i,j, n; //n代表节点数
cin>>n;
//初始化数组
memset(graph, 0, sizeof(graph));
//初始化为-1表示任何点都没有父节点,即没有一条边已加入
memset(father, -1, sizeof(father)); int k = 0, cost, temp; //接收数据
for(i = 0;i < n;i++)
for(j = 0;j < n;j++){
if(i > j){
graph[k].u = i;
graph[k].v = j;
cin>>cost;
//对于小于0的值,表示不可达,所以代价为无穷大INF
if(cost < 0){
graph[k].cost = INF;
} else {
graph[k].cost = cost;
}
k++;
continue;
}
//由于是对称的,该值无用,但得接收
cin>>temp;
} //将所有边从小到大排序
sort(graph, graph + k, cmp); //打印排序后的边
for(i = 0;i < k;i++){
cout<<i<<" "<<graph[i].u<<"->"<<graph[i].v<<": "<<graph[i].cost<<endl;
} //count为记录已经加入的边数,到n-1时截止
//sum为最小生成树的代价和
int count = 0, sum = 0; //从小到大遍历k条边
for(i = 0; i < k;i++){
//探测该边是否可加入
if(unionEdge(father, graph[i].u, graph[i].v)){
count++;
sum += graph[i].cost;
} //当加入n-1条边时,已满足连通图,则退出
if(count == n - 1) break;
} cout<<"最小生成树代价和sum : "<<sum<<endl; return 0;
}

测试例子:

7
0 5 -1 -1 -1 11 2
5 0 10 8 -1 -1 13
-1 10 0 7 -1 -1 -1
-1 8 7 0 12 9 4
-1 -1 -1 12 0 10 -1
11 -1 -1 9 10 0 3
2 13 -1 4 -1 3 0

结果:

0 6->0: 2
1 6->5: 3
2 6->3: 4
3 1->0: 5
4 3->2: 7
5 3->1: 8
6 5->3: 9
7 2->1: 10
8 5->4: 10
9 5->0: 11
10 4->3: 12
11 6->1: 13
12 2->0: 1000000
13 6->4: 1000000
14 6->2: 1000000
15 3->0: 1000000
16 5->2: 1000000
17 5->1: 1000000
18 4->2: 1000000
19 4->1: 1000000
20 4->0: 1000000
最小生成树代价和sum : 31

Kruskal算法模拟讲解的更多相关文章

  1. Dijkstra算法模拟讲解

    dijkstra算法,是一个求单源最短路径算法 其算法的特点为: 层层逼进,有点类似宽度搜索的感觉 其需要的数据结构为:                  int map[N][N] 所有点之间的权表 ...

  2. 最小生成树详细讲解(一看就懂!) & kruskal算法

    0.前言 因为本人太蒟了 我现在连NOIP的初赛都在胆战心惊 并且我甚至连最小生成树都没有学过 所以这一篇博客一定是最详细的QAQ 哈哈 请您认真看完如果有疏漏之处敬请留言指正 感谢! Thanks♪ ...

  3. 最小生成树(prime算法 & kruskal算法)和 最短路径算法(floyd算法 & dijkstra算法)

    一.主要内容: 介绍图论中两大经典问题:最小生成树问题以及最短路径问题,以及给出解决每个问题的两种不同算法. 其中最小生成树问题可参考以下题目: 题目1012:畅通工程 http://ac.jobdu ...

  4. POJ 1679 The Unique MST (次小生成树kruskal算法)

    The Unique MST 时间限制: 10 Sec  内存限制: 128 MB提交: 25  解决: 10[提交][状态][讨论版] 题目描述 Given a connected undirect ...

  5. 图的最小生成树的理解和实现:Prim和Kruskal算法

    最小生成树 一个连通图的生成树是一个极小的连通子图,它含有图中所有的顶点,但只有足以构成一棵树的n-1条边.我们将构造连通网的最小代价生成树称为最小生成树(Minimum Cost Spanning ...

  6. 最小生成树(II)与Kruskal算法

    为防止网页加载过慢,故分两章.上接https://www.cnblogs.com/Uninstalllingyi/p/10479470.html Kruskal算法——将森林合并成树 玩过瘟疫公司吗… ...

  7. 算法学习记录-图——最小生成树之Kruskal算法

    之前的Prim算法是基于顶点查找的算法,而Kruskal则是从边入手. 通俗的讲:就是希望通过 边的权值大小 来寻找最小生成树.(所有的边称为边集合,最小生成树形成的过程中的顶点集合称为W) 选取边集 ...

  8. 图论之最小生成树之Kruskal算法

    Kruskal算法,又称作为加边法,是配合并查集实现的. 图示: 如图,这是一个带权值无向图我们要求它的最小生成树. 首先,我们发现在1的所有边上,连到3的边的边权值最小,所以加上这条边. 然后在3上 ...

  9. hdu 1875 畅通project再续(kruskal算法计算最小生成树)

    畅通project再续 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

随机推荐

  1. Android 简单的FC

    直接贴log 01-02 08:17:56.589 I/ActivityManager( 312): Start proc com.android.providers.calendar for con ...

  2. linux c++ 遍历一个目录下的文件名 (包括子目录的文件名)

    最近写代码有一个要遍历目录下的每一个文件并取得这个文件的绝对路径的需求, 我们知道linux c++中有system命令所以我在代码中 先生成了一个log,然后去读log文件的每一行文件名,然后给存储 ...

  3. 《C和指针》章节后编程练习解答参考——6.6

    <C和指针>——6.6 题目: 在指定的下限.上限之间使用数组方法查找质数,并将质数提取出来. 要求: 略 解答代码: #include <stdio.h> #define U ...

  4. HTML5峰会小记

    5259月228日,在大连理工的伯川图书馆举办了一次HTML5峰会,小记一下这次峰会的内容. 名为HTML5峰会,其本质就是一次各大赞助商的轮番登场,产品介绍间隙插播一下HTML5.但是并不影响这次峰 ...

  5. 写个简单的ANT脚本来编译项目

    <?xml version="1.0" encoding="GBK"?> <project name="j2ee project&q ...

  6. bzoj 1191: [HNOI2006]超级英雄Hero 并查集 || 匈牙利算法

    1191: [HNOI2006]超级英雄Hero Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1804  Solved: 850[Submit][S ...

  7. 树莓派学习路程No.1 树莓派系统安装与登录 更换软件源 配置wifi

    在官网下载raspbian系统镜像,用Win32DiskImager写入TF卡 Image File 选择系统镜像,Device 选择TF卡盘符,Write即可.这样系统就写好了.把内存卡插进树莓派里 ...

  8. keil教程

    KEIL C51标准C编译器为8051微控制器的软件开发提供了C语言环境,但是界面是英文的好多初学者看很多教程都是一头雾水,这个相对简单的教程.KEIL C51编译器的功能不断增强,使你可以更加贴近C ...

  9. http://www.cnbc.com/2016/07/12/tensions-in-south-china-sea-to-persist-even-after-court-ruling.html

    http://www.cnbc.com/2016/07/12/tensions-in-south-china-sea-to-persist-even-after-court-ruling.html T ...

  10. swiper去除滑动设置

    有时候使用swiper并不想让它滑动,怎么设置呢? 1.noSwiping设为true 2.在slide上(或其他元素)增加类名'swiper-no-swiping',使该slide无法拖动. 案例: ...