里姆算法(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. web渗透-sqli-labs-master 下载与安装

    注意事项,写在前面. php版本一定要设置成 7 以下,7之后的mysql_都改成了mysqli_**了,用7以上版本的话会报错 *********************************** ...

  2. 干货 | Elasticsearch Nested类型深入详解(转)

    https://blog.csdn.net/laoyang360/article/details/82950393 0.概要在Elasticsearch实战场景中,我们或多或少会遇到嵌套文档的组合形式 ...

  3. IECapt、CutyCapt 生成网页快照

    IECapt.CutyCapt  生成网页快照 http://iecapt.sourceforge.net/ http://cutycapt.sourceforge.net/ 1.以管理员身份 运行c ...

  4. 阿里巴巴前端面试分享-社招(p6)

    借鉴了朋友的阿里面试经:(社招前端2年经验) 电话面 简单自我介绍, 做过哪些项目, 使用哪些技术栈 ? 如何看待前端框架选型 ? vue的如何实现双向绑定的 ? react 虚拟DOM 是什么? 如 ...

  5. Protocol Buffers介绍及例子

    Protocol Buffers介绍及例子 Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化.它很适合做数据存储或数据交换格式.可用于通讯协 ...

  6. 配置 CentOS 7 安装位置

    红框里是CentOS 7安装程序检测到的硬盘,选择你想把系统安装到哪个硬盘当中. 点击 Add disk 按钮可以添加指定的附加设备或者网络设备(通过ISCSI.FCoE等方式添加硬盘) 此处设置分区 ...

  7. Sequential Minimal Optimization(SMO,序列最小优化算法)初探

    什么是SVM SVM是Support Vector Machine(支持向量机)的英文缩写,是上世纪九十年代兴起的一种机器学习算法,在目前神经网络大行其道的情况下依然保持着生命力.有人说现在是神经网络 ...

  8. 洛谷 P2014 选课(树形背包)

    洛谷 P2014 选课(树形背包) 思路 题面:洛谷 P2014 如题这种有依赖性的任务可以用一棵树表示,因为一个儿子要访问到就必须先访问到父亲.然后,本来本题所有树是森林(没有共同祖先),但是题中的 ...

  9. 基于MVC4+EF5.0+Ajax+Json+CSS3的简单注册页面(get&post)

    使用mvc4可以很快速的创建页面,但封装的过多,难免会有些性能上的问题.所以基于此,通过使用简单的手写html,加ajax,json来创建一个注册页面,会比较干净,简洁. 本项目的环境是MVC4+EF ...

  10. Maven仓库汇总

    来源:http://tianya23.blog.51cto.com/1081650/386908 1.maven 仓库地址: 共有的仓库http://repo1.maven.org/maven2/ht ...