最小生成树(prim)
里姆算法(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)的更多相关文章
- 数据结构代码整理(线性表,栈,队列,串,二叉树,图的建立和遍历stl,最小生成树prim算法)。。持续更新中。。。
//归并排序递归方法实现 #include <iostream> #include <cstdio> using namespace std; #define maxn 100 ...
- 邻接矩阵c源码(构造邻接矩阵,深度优先遍历,广度优先遍历,最小生成树prim,kruskal算法)
matrix.c #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include < ...
- 最小生成树Prim算法(邻接矩阵和邻接表)
最小生成树,普利姆算法. 简述算法: 先初始化一棵只有一个顶点的树,以这一顶点开始,找到它的最小权值,将这条边上的令一个顶点添加到树中 再从这棵树中的所有顶点中找到一个最小权值(而且权值的另一顶点不属 ...
- 转载:最小生成树-Prim算法和Kruskal算法
本文摘自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html 最小生成树-Prim算法和Kruskal算法 Prim算 ...
- 最小生成树Prim
首先解释什么是最小生成树,最小生成树是指在一张图中找出一棵树,任意两点的距离已经是最短的了. 算法要点: 1.用book数组存放访问过的节点. 2.用dis数组保存对应下标的点到树的最近距离,这里要注 ...
- 最小生成树—prim算法
最小生成树prim算法实现 所谓生成树,就是n个点之间连成n-1条边的图形.而最小生成树,就是权值(两点间直线的值)之和的最小值. 首先,要用二维数组记录点和权值.如上图所示无向图: int map[ ...
- 最小生成树Prim算法和Kruskal算法
Prim算法(使用visited数组实现) Prim算法求最小生成树的时候和边数无关,和顶点树有关,所以适合求解稠密网的最小生成树. Prim算法的步骤包括: 1. 将一个图分为两部分,一部分归为点集 ...
- 最小生成树 Prim Kruskal
layout: post title: 最小生成树 Prim Kruskal date: 2017-04-29 tag: 数据结构和算法 --- 目录 TOC {:toc} 最小生成树Minimum ...
- POJ1258 (最小生成树prim)
Agri-Net Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 46319 Accepted: 19052 Descri ...
- poj1861 最小生成树 prim & kruskal
// poj1861 最小生成树 prim & kruskal // // 一个水题,为的仅仅是回味一下模板.日后好有个照顾不是 #include <cstdio> #includ ...
随机推荐
- 自定义JSON返回字段
今天看到一篇文章,里面介绍了如何自定义返回json字段,感觉挺好用的,这里学习一下. 实现工具类: /** * @author fengzp * @date 17/2/20上午10:34 * @ema ...
- springboot集成JsonRpc2.0
导入依赖的jar: 配置AutoJsonRpcServiceImplExporter: 接口文件: 实现类: 测试:
- java_对象序列化
对象序列化(serializable) 序列化读:ObjectInputStream ois=new ObjectInputStream(new FileInputStream("./gg ...
- P4542 [ZJOI2011]营救皮卡丘
题目链接 题意分析 我们仔细分析一下 发现题目要求用最多\(k\)条路径实现最小权覆盖 首先由于最小路径覆盖针对的是有向图 但是这是一个无向图 所以我们面向对象编程 我们维护一个数组\(d[i][j] ...
- 深入浅出理解基于 Kafka 和 ZooKeeper 的分布式消息队列
消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题.实现高性能,高可用,可伸缩和最终一致性架构,是大型分布式系统不可缺少的中间件. 本场 Chat 主要内容: Kafk ...
- linux系统服务管理
centos7的服务管理命令 systemctl start 服务名称 systemctl stop 服务名称 systemctl status 服务名称 systemctl restart 服务名称 ...
- 怎么搭建一个5T的私有云盘
视频 点击打开视频 下载地址 免费域名网址: https://www.freewebhostingarea.com/ ftp工具: http://t.cn/EXWxYUI oneindex: http ...
- 第1章—Spring之旅—简化Spring的java开发
简化Spring的java开发 1.1简介 区别于EJB的特性 简化javaBean,为了降低java开发的复杂性,Spring采取了以下4种关键策略: 基于POJO的轻量级和最小入侵性编程 通过依赖 ...
- ifram的使用 左边是<a>链接 右边是对应网页嵌套的显示网页链接内容 和toggle的收放用法
1.ifram的使用 左边是<a>链接 右边是对应网页嵌套的显示网页链接内容 <div class="container"> <div class= ...
- GitHub注册和Git安装
一.注册GitHub GitHub官方地址:https://github.com. 在浏览器中打开GitHub网址,通过首页进行注册,如下图所示. 二.安装Git Git官方下载地址:http://g ...