里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (graph theory)),且其所有边的权值之和亦为最小。

介绍如下:

http://baike.baidu.com/link?url=nDhHyOlu8i90Hm5bjUycarVdBPN8BXQvnv8NGwl0g4MLlLkmkFLwf7xs1-JBWCRkQw5qDU6cIwh1ov7fyRRxQK

原理可以参考这几篇文章:

http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html

http://blog.csdn.net/weinierbian/article/details/8059129

http://blog.chinaunix.net/uid-25324849-id-2182922.html

prim算法适合稠密图,邻接矩阵时间复杂度为O(n^2),邻接表为O(eloge),其时间复杂度与边得数目无关。

而kruskal算法的时间复杂度为O(eloge)跟边的数目有关,适合稀疏图。

邻接矩阵实现:

 #include <iostream>
using namespace std; #define MAXVEX 20
#define MAXEDGE 20
#define INFINITY 65535 typedef struct
{
int vexs[MAXVEX];
int arc[MAXVEX][MAXVEX];
int numVertexes,numEdges;
}MGraph; typedef int Patharc[MAXVEX];
typedef int ShortPathTable[MAXVEX]; bool visited[MAXVEX];//保存已访问的数组
int father[MAXVEX];
int closeset[MAXVEX]; void CreateGraph(MGraph* G)
{
cout<<"请输入边数和顶点数:\n";
int d,n,i,j;
cin>>d>>n;
G->numVertexes = n;
G->numEdges = d; //给顶点和边初始化
for(i = ;i<G->numVertexes;i++)
G->vexs[i] = i;
for(i = ;i<G->numVertexes;i++)
{
for(j = ;j<G->numVertexes;j++)
{
if(i==j)
G->arc[i][j] = ;
else
G->arc[i][j] = G->arc[j][i] = INFINITY;
}
} G->arc[][]=;
G->arc[][]=;
G->arc[][]=;
G->arc[][]=;
G->arc[][]=; G->arc[][]=;
G->arc[][]=;
G->arc[][]=;
G->arc[][]=;
G->arc[][]=; G->arc[][]=;
G->arc[][]=;
G->arc[][]=;
G->arc[][]=;
G->arc[][]=; G->arc[][]=; for(i = ;i<G->numVertexes;i++)
{
for(j = i;j<G->numVertexes;j++)
{
G->arc[j][i] = G->arc[i][j];
}
}
} int prim(MGraph G, Patharc *P, ShortPathTable *D)
{
int v,w; //init
for(v = ;v<G.numVertexes;v++)
{
visited[v] = false;
(*D)[v] = G.arc[][v];
father[v] = -;
closeset[v] = ;
}
visited[] = true; int len = ;
int nlen,nid; //求得下一个符合条件的点
for(v = ;v<G.numVertexes;v++)
{
nlen = INFINITY;
for(w = ;w<G.numVertexes;w++)
{
if(!visited[w] && (*D)[w]<nlen)
{
nlen = (*D)[w];
nid = w;
}
} len += nlen;
visited[nid] = true;
father[nid] = closeset[nid]; for(w = ;w<G.numVertexes;w++)
{
if(!visited[w] && (*D)[w]>G.arc[nid][w])
{
(*D)[w] = G.arc[nid][w];
closeset[w] = nid;
}
} } return len; } int main()
{
int v0,i,j; MGraph G; Patharc P;
ShortPathTable D; CreateGraph(&G); int d = prim(G,&P,&D); cout<<"最小树如下:\n";
for(i = ;i<G.numVertexes;i++)
{
cout<<"("<<i<<","<<father[i]<<") ";
}
cout<<endl; cout<<"最短路径长度为:\n"; cout<<d<<endl; return ; }

我是用vector和pair的邻接表实现的,然后用两个list保存两个集合,一个最小生成树集,一个其他集

实现如下:

 #include <iostream>
#include <vector>
#include <queue>
#include <list>
using namespace std; vector<pair<int,int> > eg[]; vector<pair<int,int> > result; typedef pair<int,int> pa; bool visit[]; list<int> setOfPrim; list<int> outOfPrim; int lowcost[] = {}; void prim(int n,int d)
{
int min,aim,sta;
bool is; list<int>::iterator sop;//最小树集合
list<int>::iterator oop;//其他集合
vector<pair<int,int> >::iterator it; setOfPrim.push_back();//放入起始点0进最小树集合 //初始化其他集合
for(int i = ;i<n;i++)
outOfPrim.push_back(i); while(!outOfPrim.empty())//其他集合不为空
{
//遍历最小树集合,sop,寻找与集合最近的点
min = <<;
for(sop = setOfPrim.begin();sop!=setOfPrim.end();sop++)
{
//遍历sop邻接点
for(int i = ;i<eg[*sop].size();i++)
{
pa x = eg[*sop][i];
is = false; //如果点属于oop集合
for(oop = outOfPrim.begin();oop!=outOfPrim.end();oop++)
{
if(*oop == x.first)
{
is = true;
}
} if(is)
{
if(x.second<min)
{
min = x.second;
aim = x.first;
sta = *sop;
}
//min存放了离sop集合最近的点的距离
//aim存放了点的序号
}
}
} setOfPrim.push_back(aim);
result.push_back(make_pair(sta,aim));
for(oop = outOfPrim.begin(); oop != outOfPrim.end(); )
{
if(*oop == aim)
{
oop = outOfPrim.erase(oop);
if(outOfPrim.empty())
break;
}
else
oop++;
}
cout<<"The set of prim:\n";
for(sop = setOfPrim.begin(); sop != setOfPrim.end();sop++)
{
cout<<*sop<<" ";
}
cout<<"\nThe set of not prim:\n";
for(oop = outOfPrim.begin(); oop != outOfPrim.end();oop++)
{
cout<<*oop<<" ";
}
cout<<endl; for(it = result.begin();it!=result.end();it++)
{ cout<<"("<<(*it).first<<","<<(*it).second<<")";
}
cout<<endl<<endl;
}
} int main()
{
int n,d;
cin>>n>>d;
for(int i = ;i<d;i++)
{
int t,s,w;
cin>>t>>s>>w;
eg[t].push_back(make_pair(s,w));
eg[s].push_back(make_pair(t,w));
}
prim(n,d); }
/*
6 8
0 1 2
0 3 4
1 4 4
2 0 5
2 5 2
3 4 3
3 5 7
5 4 3
*/

另外,因为prim算法和Dijkstra算法很像,这篇文章有讲两者之间的区别:

http://www.cnblogs.com/CheeseZH/archive/2012/10/09/2717106.html

最小生成树(prim)的更多相关文章

  1. 数据结构代码整理(线性表,栈,队列,串,二叉树,图的建立和遍历stl,最小生成树prim算法)。。持续更新中。。。

    //归并排序递归方法实现 #include <iostream> #include <cstdio> using namespace std; #define maxn 100 ...

  2. 邻接矩阵c源码(构造邻接矩阵,深度优先遍历,广度优先遍历,最小生成树prim,kruskal算法)

    matrix.c #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include < ...

  3. 最小生成树Prim算法(邻接矩阵和邻接表)

    最小生成树,普利姆算法. 简述算法: 先初始化一棵只有一个顶点的树,以这一顶点开始,找到它的最小权值,将这条边上的令一个顶点添加到树中 再从这棵树中的所有顶点中找到一个最小权值(而且权值的另一顶点不属 ...

  4. 转载:最小生成树-Prim算法和Kruskal算法

    本文摘自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html 最小生成树-Prim算法和Kruskal算法 Prim算 ...

  5. 最小生成树Prim

    首先解释什么是最小生成树,最小生成树是指在一张图中找出一棵树,任意两点的距离已经是最短的了. 算法要点: 1.用book数组存放访问过的节点. 2.用dis数组保存对应下标的点到树的最近距离,这里要注 ...

  6. 最小生成树—prim算法

    最小生成树prim算法实现 所谓生成树,就是n个点之间连成n-1条边的图形.而最小生成树,就是权值(两点间直线的值)之和的最小值. 首先,要用二维数组记录点和权值.如上图所示无向图: int map[ ...

  7. 最小生成树Prim算法和Kruskal算法

    Prim算法(使用visited数组实现) Prim算法求最小生成树的时候和边数无关,和顶点树有关,所以适合求解稠密网的最小生成树. Prim算法的步骤包括: 1. 将一个图分为两部分,一部分归为点集 ...

  8. 最小生成树 Prim Kruskal

    layout: post title: 最小生成树 Prim Kruskal date: 2017-04-29 tag: 数据结构和算法 --- 目录 TOC {:toc} 最小生成树Minimum ...

  9. POJ1258 (最小生成树prim)

    Agri-Net Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 46319   Accepted: 19052 Descri ...

  10. poj1861 最小生成树 prim &amp; kruskal

    // poj1861 最小生成树 prim & kruskal // // 一个水题,为的仅仅是回味一下模板.日后好有个照顾不是 #include <cstdio> #includ ...

随机推荐

  1. 无法启动DISTRIBUTED TRANSACTION COORDINATOR解决方法

    有时候我们需要进行COM应用程序的权限设置,控制面板-->管理工具-->组件服务-->然后依此展开:组件服务-->计算机-->我的电脑-->DCOM 配置,接下来找 ...

  2. [Swift]遍历字符串

    Swift中无法再使用传统形式的for循环. //传统for循环形式不适用于Swift for(单次表达式;条件表达式;末尾循环体){中间循环体:} 字符串遍历方法1:使用该indices属性可以访问 ...

  3. Jmeter Plugins----- Transactions per Second 配置项

    Jmeter Plugins---version 0.5.5 官方解释: Transactions per Second since 0.3.0 This graph shows the number ...

  4. @ModelAttribute注解和POJO传参过程

    1.@ModelAttribute注解 @ModelAttribute主要有三个用途,对方法进行注解,对参数进行注解,还有@ModelAttribute和@RequestMapping一起对方法进行注 ...

  5. Python3 操作系统与路径 模块(os / os.path / pathlib)

    #!/usr/bin/env python # coding=utf-8 __author__ = 'Luzhuo' __date__ = '2017/5/7' import os def os_de ...

  6. date命令的基本用法

    date设置时间 设置时间:-s参数 date -s "20190426 15:22:33" date查看时间差  (-d参数多用于脚本) 查看时间差:-d参数date -d &q ...

  7. jedis 连接redis

    一,  单机版连接 @Test public void testJedis() { //1. 创建jedis 对象 Jedis jedis = new Jedis("192.168.88.1 ...

  8. [Xamarin] 產生專案的AndroidManifest.xml (转帖)

    紀錄一下 Xamarin 如何開啟 AndroidManifest.xml,因為這跟權限有關係,每個Android App幾乎都要設定 每次都想Add File 去增加但是其實是不對的 工具上面不管是 ...

  9. (转)CentOS7安装KVM虚拟机详解

    原文:https://github.com/jaywcjlove/handbook/blob/master/CentOS/CentOS7%E5%AE%89%E8%A3%85KVM%E8%99%9A%E ...

  10. 关于JNI调用从eclipse转到Android Studio遇到的问题(总结)

    将一个小应用从eclipse开发迁移到android studio,程序中有native代码实现,在eclipse是靠Android.mk这么个mk文件来组织编译的,但到android studio上 ...