最小生成树之Prim算法 优先队列版本
来源:互联网 发布:mysql中full join报错 编辑:程序博客网 时间:2024/05/29 18:28
http://www.cppblog.com/tanky-woo/archive/2013/02/18/126940.html
这个博客对prim讲解的很好
如果用传统的做法每次都要将集合内的元素遍历一遍,再与集合外的元素判断是否相连,再找出最小权值,然后把带有最小权值的那个终点记录下来,插入到集合内。
下次循环再从集合的第一个元素开始遍历,这样会浪费很多时间,于是乎,我想能不能把之前已经遍历过的顶点而且不是最小权的那些顶点存入列表中,下次再遍历的时候可以接着用,只需要把新的顶点插入进去就行了,那么怎么输出最小的权呢,大家都知道有个优先队列,就是把队列中的权值按由小到大排列,每次只需要把top()的权值pop掉就行了。
说了这么多,我们举个栗子(图就用上面那个博客的prim图)
假如从顶点1开始,与1相连的有1-2 1-3 1-4 找到1-3的权值为1 最小,于是把3这个终点的所有的相连的边插入到队列中,即3-5 3-6 3-2 3-4 因为1这个顶点已经被标记过所以,
3-1就不插入了,所以现在的队列中有 1-2 1-4 3-2 3-4 3-5 3-6 再找到top的最小的权值为3-6这个边的权4,所以把6记录下来,把3-6这个边pop掉,再重复之前的找和6相连的边。。。。。
我在写代码的时候遇到好几个问题。
比如我在把3插入队列之后,怎么不用遍历找出和3相连的边,解决办法就是用代码中的link数组来保存与3对应的边的终点,
那么和以3为起点的边有很多,那有几个呢,link[p][link[p][0]++] = q;这个就是解决办法每有重复的顶点插入进去,link[p][0]就会++,最后link[p][0]就是与p顶点相连的边数,
link[3][1] = 2 (表示以3作为顶点的第一条边的终点为2 即 3-2这个边)
link[3][2] = 4 同理表示 3-4为以3作为顶点的第二条边
下面贴出我的代码
#include <iostream>#include <queue>#include <map>#include <cstring>using namespace std;#define maxint 0x3f3f3f3f#define maxnum 1051int link[maxnum][maxnum];int c[maxnum][maxnum];int sum,n;//sum为最小权之和,n为顶点个数struct node{int s;//起点int e;//终点int w;//权};bool operator < (const node &a,const node &b){return a.w > b.w;}void prim(int s){int i,j,k,m,t,u,total;int vis[maxnum];memset(vis,0,sizeof(vis));priority_queue <node> qq;struct node nn;total = 1;vis[s] = 1;sum = 0;while(total < n){for(i=1;i<link[s][0];i++){if(!vis[link[s][i]]){nn.s = s;nn.e = link[s][i];nn.w = c[s][nn.e];qq.push(nn);}}while(!qq.empty() && vis[qq.top().e])//遇到顶点和集合外的顶点没有相连的qq.pop();//刚巧这个点作为终点是最短的,因为这个顶点没背标记过,所以会错误的计入在内nn = qq.top();s = nn.e;sum += nn.w;//cout<<nn.s<<" "<<nn.e<<" "<<nn.w<<endl;vis[s] = 1;//标记为集合内的元素qq.pop();total++;}}int main(){int i,j,k;int line,len;int t,s,d,p,q;cin>>n>>line;for(i=1;i<=n;i++){link[i][0] = 1;}for(i=1;i<=line;i++){cin>>p>>q>>len;c[p][q] = c[q][p] = len;link[p][link[p][0]++] = q;link[q][link[q][0]++] = p;}cin>>s;//输入起始点prim(s);cout<<sum<<endl;return 0;}
如有错误 欢迎指正
- 最小生成树之Prim算法 优先队列版本
- 最小生成树之prim算法(优先队列优化)
- 图论入门(3):最小生成树之Prim算法(以及优先队列的bug修正)
- 图基本算法 最小生成树 Prim算法(邻接表/邻接矩阵+优先队列STL)
- 最小生成树模板(Prim+优先队列)
- poj 1258 最小生成树 prim+优先队列
- 5253 连接的管道【最小生成树prim+优先队列】
- 最小生成树之Prime算法(基于优先队列)
- 最小生成树算法之Prim算法
- 最小生成树算法之Prim算法
- 最小生成树算法之prim算法
- 最小优先队列+prim
- 最小生成树之Prim算法
- 最小生成树算法之prim
- 最小生成树之prim算法
- 【算法】最小生成树之prim
- 最小生成树之prim算法
- 最小生成树算法之Prim
- TCP中的多线程
- jQuery选择器及jQuery事件
- catch that cow
- Java中异常的基本应用(一)
- iOS 单独设置某个控制器横屏 —— HERO博客
- 最小生成树之Prim算法 优先队列版本
- Android 刷新UI界面,线程间通讯方法总结,Android 自学之路
- 使用facl和mount实现某用户对某个目录的访问控制
- Windows下使用winpcap-2.1ARP探测局域网活动主机(发送ARP请求)
- ReactJS学习笔记(四)-条件判断的几种形式
- 如何判断一个数字能否同时被两个数整除;
- SpringMVC-2016-04-06
- Xcode 7智能测试化工具XCTestCase学习
- Java入门 第一季第一章 Java初体验