最小生成树是图的一部分,一般求最小生成树用Prim算法和Kruskal算法。

对于Prim算法,思想是:在访问过的顶点和未访问的顶点之间选择权值最小的边。Prim算法是基于顶点的操作,适合于顶点较少,边较多的图。

对于Kruskal算法,思想是:直接从图中选择权值最小的边,并且已选择的边不能构成连通图。Kruskal算法是基于边的操作,适合于边较少,顶点较多的图。

Prim算法,在此我用了关联容器pair作为边的存储结构:

//普里姆算法
int Prim(const int G[][VNUM], vector<pair<int, int> > &edge)
{
int w = 0; //权重
vector<int> visited(VNUM, 0); //已访问节点集合
//初始化
visited[0] = 1; //0号节点已访问
//循环VNUM-1次
int u, v;
for(int number = 1; number < VNUM; ++number)
{
int min = M;
for(int i = 0; i != VNUM; ++i) //一次循环有一个节点入栈
{
if(visited[i] == 1)
{
for(int j = 1; j != VNUM; ++j) //判断边(i, j)的权值,i为已访问节点,j为未访问节点
{ if(visited[j] == 0 && G[i][j] < min)
{
min = G[i][j];
v = i;
u = j;
}
}
}
}
w += G[v][u];
visited[u] = 1;
edge[number-1].first = v;
edge[number-1].second = u;
}
return w;
}

克鲁斯卡尔算法的最小生成树结构用并查集表示,并查集在次主要用来判断已选择的边是否构成连通图,如果对应顶点x,y的FindRoot()操作返回的结果相同,即他们的根相同,则能够成连通图,说明选择的边不满足条件。

//并查集结构
class DisjointSet{
public:
vector<int> father;
DisjointSet(int VNUM){
father.resize(VNUM, -1);
}
int FindRoot(int x)
{
while(father[x] >= 0)
x = father[x];
return x;
}
void Union(int x, int y)
{
father[FindRoot(x)] = FindRoot(y);
}
};
//Kruskal
int Kruskal(const int G[][VNUM], vector<pair<int, int> > &edge)
{
int min = M;
int w = 0;
int v, u;
DisjointSet V(VNUM);
for(int num = 0; num != VNUM-1; ++num)
{
min = M;
for(int i = 0; i != VNUM; ++i)
{
for(int j = 0; j != VNUM; ++j)
{
if(G[i][j] < min && V.FindRoot(i) != V.FindRoot(j))
{
min = G[i][j];
v = i;
u = j;
}
}
}
w += G[u][v];
V.Union(u, v);
edge[num].first = v;
edge[num].second = u;
}
return w;
}

下面是主程序:

/*************************
Date : 2013-9-20
Author : DVD0423
Function: 无向图的最小生成树
******************&******/
#include <iostream>
#include <vector>
#include <utility>
using namespace std;
const int M = 10; //两节点无边权值用M表示
const int VNUM = 6; int Prim(const int G[][VNUM], vector<pair<int, int> > &edge);
int Kruskal(const int G[][VNUM], vector<pair<int, int> > &edge); int main()
{
const int G[VNUM][VNUM] = {
M, 9, 1, M, 7, 2,
9, M, 5, 1, M, 6,
1, 5, M, 4, 2, 6,
M, 1, 4, M, 9, 3,
7, M, 2, 9, M, M,
2, 6, 6, 3, M, M
};
vector<pair<int, int> > edge(VNUM-1); //Prim
cout<<"普里姆算法:"<<endl;
cout<<"总路径长度:"<<Prim(G, edge)<<endl;
for(int i = 0; i != VNUM-1; ++i)
cout<<"("<<edge[i].first<<", "<<edge[i].second<<")"<<endl; //Kruskal
cout<<"克鲁斯卡尔算法:"<<endl;
cout<<"总路径长度:"<<Kruskal(G, edge)<<endl;
for(int i = 0; i != VNUM-1; ++i)
cout<<"("<<edge[i].first<<", "<<edge[i].second<<")"<<endl; return 0;
}

输出结果如下:

C++数据结构之最小生成树的更多相关文章

  1. 【数据结构】 最小生成树(四)——利用kruskal算法搞定例题×3+变形+一道大水题

    在这一专辑(最小生成树)中的上一期讲到了prim算法,但是prim算法比较难懂,为了避免看不懂,就先用kruskal算法写题吧,下面将会将三道例题,加一道变形,以及一道大水题,水到不用高级数据结构,建 ...

  2. 【数据结构】 最小生成树(三)——prim算法

    上一期介绍到了kruskal算法,这个算法诞生于1956年,重难点就是如何判断是否形成回路,此处要用到并查集,不会用当然会觉得难,今天介绍的prim算法在kruskal算法之后一年(即1957年)诞生 ...

  3. 【数据结构】 最小生成树(二)——kruskal算法

    上一期说完了什么是最小生成树,这一期咱们来介绍求最小生成树的算法:kruskal算法,适用于稀疏图,也就是同样个数的节点,边越少就越快,到了数据结构与算法这个阶段了,做题靠的就是速度快,时间复杂度小. ...

  4. 数据结构:最小生成树--Prim算法

    最小生成树:Prim算法 最小生成树 给定一无向带权图.顶点数是n,要使图连通仅仅需n-1条边.若这n-1条边的权值和最小,则称有这n个顶点和n-1条边构成了图的最小生成树(minimum-cost ...

  5. 数据结构:最小生成树--Kruskal算法

    Kruskal算法 Kruskal算法 求解最小生成树的还有一种常见算法是Kruskal算法.它比Prim算法更直观.从直观上看,Kruskal算法的做法是:每次都从剩余边中选取权值最小的,当然,这条 ...

  6. 数据结构--画画--最小生成树(Prim算法)

    通信网络的最小生成树配置,它是使右侧的生成树值并最小化.经常使用Prim和Kruskal算法.看Prim算法:以防万一N={V,{E}}它是在通信网络,TE它是N设置边的最小生成树.从算法U={u0} ...

  7. 数据结构之最小生成树Prim算法

    普里姆算法介绍 普里姆(Prim)算法,是用来求加权连通图的最小生成树算法 基本思想:对于图G而言,V是所有顶点的集合:现在,设置两个新的集合U和T,其中U用于存放G的最小生成树中的顶点,T存放G的最 ...

  8. 数据结构之最小生成树Kruskal算法

    1. 克鲁斯卡算法介绍 克鲁斯卡尔(Kruskal)算法,是用来求加权连通图的最小生成树的算法. 基本思想:按照权值从小到大的顺序选择n-1条边,并保证这n-1条边不构成回路. 具体做法:首先构造一个 ...

  9. 【数据结构】最小生成树之prim算法和kruskal算法

    在日常生活中解决问题经常需要考虑最优的问题,而最小生成树就是其中的一种.看了很多博客,先总结如下,只需要您20分钟的时间,就能完全理解. 比如:有四个村庄要修四条路,让村子能两两联系起来,这时就有最优 ...

随机推荐

  1. Kth Smallest Element in a BST 解答

    Question Given a binary search tree, write a function kthSmallest to find the kth smallest element i ...

  2. poj1001(高精度)

                                                               Exponentiation Time Limit: 500MS   Memory ...

  3. SqlServer 数据库日志无法收缩处理过程

    今天按常用方法收缩一个测试用的数据库日志,发现没法收缩! dbcc sqlperf(logspace)     USE [dbname] GO ALTER DATABASE [dbname] SET  ...

  4. VF(动态规划)

    VF 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描述 Vasya is the beginning mathematician. He decided to make a ...

  5. mysql、sqlServer、hsql、oracle、db2各数据库支持的字段类型与最大精度

  6. RMAN备份各种物理文件

    RMAN运行脚本的方式:RMAN TARGET / @backup_db.rmanRMAN TARGET / cmdfile=backup_db.rman在RMAN中执行操作系统中保存的脚本:RMAN ...

  7. 【二分查找+优化O(n)】【续UVA1121】Subsequence

    之前的二分答案做法 http://blog.csdn.net/zy691357966/article/details/40212215 二分查找做法: 我们首先试试只枚举终点.对于终点j,我们的目标是 ...

  8. mysql 分库分表的方法

    分表后怎么做全文搜索 1.merge方式分表(不好) 2. 使用 sql union 3 使用Sphinx全文检索引擎 一,先说一下为什么要分表 当一张的数据达到几百万时,你查询一次所花的时间会变多, ...

  9. ueditor+asp.net异步提交,可以实现了,嘿嘿

    之前没用过Ueditor去异步提交,最近项目需要用到这个,就下了个来用,结果可能没仔细去看Ueditor的相关介绍文档,然后自己也郁闷了一下才把它弄出来,现在可以实现异步提交了,松口气,把代码贴出来, ...

  10. SqlServer判断数据库、表、存储过程、函数是否存在

    假设场景是: 需要给一个脚本给客户更新, 这个对象可能存在或不存在 -- 更新存储过程 USE [数据库名] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ...