Dijkstra算法优先队列实现与Bellman_Ford队列实现的理解
/*
Dijkstra算法用优先队列来实现,实现了每一条边最多遍历一次。 要知道,我们从队列头部找到的都是到
已经"建好树"的最短距离以及该节点编号, 并由该节点去更新 树根 到其他点(被更新的节点可以在队列中
,也可以是非队列中的节点)的距离 。 ////如果v节点的到更新,则直接放入队列中(pair<d[v], v>)不会重复放入到队列中 如果某个节点从队列中出来的时候,如果cur.first != dist[cur.second] 就是 cur.second这个节点一开始
被更新的最短距离值 和 现在得到的最短距离的值dist[cur.second] 不想等,说明该节点已经被之前队列中
具有更短距离的节点更新过了, 那么新的节点pair(dist[cur.second], cur.second)再次放入优先队列中,用来跟新其他节点的最短距离。 如果想等,则dist[cur.second]就是cur.second最终的最短距离!
*/
#include<iostream>
#include<queue>
#include<cstring>
#define N 1000
using namespace std; class EDGE
{
public:
int u, v, w;
int next;//和节点 u 相连的下一条边的编号
}; EDGE edge[*N]; typedef pair<int, int>pii;//pair<距离,节点号> int first[N];//最多有N个节点 ,建立每个节点和其相连的边的关系
int dist[N];//源点到各个点的最短距离 int n, m;//节点数,边数 bool operator >(pii a, pii b)
{
if(a.first==b.first)
return a.second > b.second;
return a.first > b.first;//按照最短的距离值在队列的前段
} priority_queue<pii, vector<pii>, greater<pii> >q; void Dijkstra()
{
pii cur;
memset(dist, 0x3f, sizeof(dist));
dist[]=;//另节点 1 为源点
q.push(make_pair(, ));
while(!q.empty())
{
cur=q.top();
q.pop();
if(cur.first != dist[cur.second]) continue;// 不等于的话说明该节点的值已经经过其他节点松弛为更短的距离值了
for(int e=first[cur.second]; e!=-; e=edge[e].next)
if(dist[edge[e].v]>dist[edge[e].u]+edge[e].w)
{
dist[edge[e].v]=dist[edge[e].u]+edge[e].w;
q.push(make_pair(dist[edge[e].v], edge[e].v));//将更新之后的节点的放入队列之中
}
}
} int main()
{
int i;
cin>>n>>m;
for(i=; i<=n; ++i)
first[i]=-;
for(i=; i<m; ++i)
{
cin>>edge[i].u>>edge[i].v>>edge[i].w;
edge[edge[i].u].next=first[edge[i].u];
first[edge[i].u]=i;
}
Dijkstra();
for(i=; i<=n; ++i)
cout<<"1->"<<i<<":"<<dist[i]<<endl;
return ;
}
/*
Bellman_Ford算法用队列实现和 Dijkstra算法用优先队列来实现相同的地方是,都是 层次 更新到节点的最短距离,
3 都是将具有最短距离的节点(如果不在队列中)放入队列中
Bellman_Ford算法中实现的是带有负权图的最短距离,因为负权的关系,这样可能使得某个
节点的最短路径的值一直被更新(比如存在负权回路的时候),所以被更新的节点(如果不在队列中)一直会进入队列中
*/
#include<iostream>
#include<queue>
#include<cstring>
#define N 1000
using namespace std; class EDGE
{
public:
int u, v, w;
int next;//和节点 u 相连的下一条边的编号
}; EDGE edge[*N]; int first[N];//最多有N个节点 ,建立每个节点和其相连的边的关系
int dist[N];//源点到各个点的最短距离
int cnt[N];//记录每个节点在队列中出现的次数
int vis[N];//记录当前的节点是否已经在队列中 int n, m;//节点数,边数 queue<int>q; int Bellman_Ford()
{
int cur;
memset(dist, 0x3f, sizeof(dist));
dist[]=;//另节点 1 为源点
q.push();
while(!q.empty())
{
cur=q.front();
q.pop();
vis[cur]=;//出队列
++cnt[cur];
if(cnt[cur]>n-)//如果不存在负权回路,那么某个节点的最多被更新的次数为 n-1 次
return ;
for(int e=first[cur]; e!=-; e=edge[e].next)
if(dist[edge[e].v]>dist[edge[e].u]+edge[e].w)
{
dist[edge[e].v]=dist[edge[e].u]+edge[e].w;
if(!vis[edge[e].v])//本跟新的节点没有在队列中
{
q.push(edge[e].v);//将更新之后的节点的放入队列之中
vis[edge[e].v]=;//放入队列
}
}
}
return ;
} int main()
{
int i;
cin>>n>>m;
for(i=; i<=n; ++i)
first[i]=-;
for(i=; i<m; ++i)
{
cin>>edge[i].u>>edge[i].v>>edge[i].w;
edge[edge[i].u].next=first[edge[i].u];
first[edge[i].u]=i;
}
if(!Bellman_Ford())//表示存在负权回路
cout<<"不存在最短路径"<<endl;
else
{
for(i=; i<=n; ++i)
cout<<"1->"<<i<<":"<<dist[i]<<endl;
}
return ;
}
Dijkstra算法优先队列实现与Bellman_Ford队列实现的理解的更多相关文章
- dijkstra算法优先队列
d[i] 是起点到 I 节点的最短距离 void Dijkstra(int s) { priority_queue<P, vector<P>, greater<P> &g ...
- 最短路模板(Dijkstra & Dijkstra算法+堆优化 & bellman_ford & 单源最短路SPFA)
关于几个的区别和联系:http://www.cnblogs.com/zswbky/p/5432353.html d.每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个(草儿家到 ...
- 基于STL优先队列和邻接表的dijkstra算法
首先说下STL优先队列的局限性,那就是只提供入队.出队.取得队首元素的值的功能,而dijkstra算法的堆优化需要能够随机访问队列中某个节点(来更新源点节点的最短距离). 看似可以用vector配合m ...
- HDU 1535 Invitation Cards(逆向思维+邻接表+优先队列的Dijkstra算法)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1535 Problem Description In the age of television, n ...
- dijkstra算法与优先队列
这是鄙人的第一篇技术博客,作为算法小菜鸟外加轻度写作障碍者,写技术博客也算是对自己的一种挑战和鞭策吧~ 言归正传,什么是dijkstra算法呢? -dijkstra算法是一种解决最短路径问题的简单有效 ...
- Dijkstra算法(朴素实现、优先队列优化)
Dijkstra算法只能求取边的权重为非负的图的最短路径,而Bellman-Ford算法可以求取边的权重为负的图的最短路径(但Bellman-Ford算法在图中存在负环的情况下,最短路径是不存在的(负 ...
- dijkstra算法之优先队列优化
github地址:https://github.com/muzhailong/dijkstra-PriorityQueue 1.题目 分析与解题思路 dijkstra算法是典型的用来解决单源最短路径的 ...
- 单源最短路径算法——Bellman-ford算法和Dijkstra算法
BellMan-ford算法描述 1.初始化:将除源点外的所有顶点的最短距离估计值 dist[v] ← +∞, dist[s] ←0; 2.迭代求解:反复对边集E中的每条边进行松弛操作,使得顶点集V ...
- ACM: HDU 1874 畅通工程续-Dijkstra算法
HDU 1874 畅通工程续 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Desc ...
随机推荐
- bzoj1051Tarjan裸题
tarjan缩点+判断出度为0的点 所以不需要新建边 #include <cstdio> ,time=,T=,sum=,ans=; ],to[],nex[],fir[],dfn[],low ...
- C#调用win32 api程序实例
1.声明static extern 方法,使用DllImport特性 class MyClass { [DllImport("kernel32", SetLastError = t ...
- less杂记
less最管用的就是嵌套,让css关系很清晰,虽然增加代码量,我认为也是值得的,不用less的话会有些怀念嵌套的各种优势,但是层次太多,嵌套太长会让可读性变得很差,这点也是个问题. 1.less中的& ...
- oracle 字符串分割
); create or replace function strsplit2(p_value varchar2, p_split varchar2 := ',') return str_split ...
- oracle遍历表更新另一个表(一对多)
declare cursor cur_test is select t.txt_desig, m.segment_id, s.code_type_direct, case when s.uom_dis ...
- [IOS]swift 使用AVOS的API
避免写后台代码,但保证app能够有后台,使用了AVOS这个产品来帮助自己的app联网,AVOS是很强大的云服务,基本原理和Parse差不多,只是parse在国外可能对国内用户联网速度上有点限制. 下面 ...
- iOS 琐碎点------切某个或某几个角的圆角
不说废话----------> 1.如果是切四个角的圆角,代码示例: self.picImage.layer.cornerRadius = 8; self.picImage.layer.mask ...
- Javascript中call和apply的区别和用法
JavaScript中有一个call和apply方法,其作用基本相同,但也有略微的区别.其实就是更改对象的内部指针,即改变对象的this指向的内容.这在面向对象的js编程过程中有时是很有用的.call ...
- MySql怎样去掉某个字段最后的逗号或最后的字
update 表 set 字段=left(字段,char_length(字段)-1) where right(字段,1)=',';
- siteserver cms选择栏目搜索无效
标签必须以空格分开,且option 的value必须给id不能给名称