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[2*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]=0;//另节点 1 为源点
   q.push(make_pair(0, 1));
   while(!q.empty()) 
   {
      cur=q.top();
      q.pop();
      if(cur.first != dist[cur.second])  continue;// 不等于的话说明该节点的值已经经过其他节点松弛为更短的距离值了 
      for(int e=first[cur.second]; e!=-1; 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=1; i<=n; ++i)
     first[i]=-1; 
   for(i=0; 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=2; i<=n; ++i)
     cout<<"1->"<<i<<":"<<dist[i]<<endl; 
   return 0;
/*
Bellman_Ford算法用队列实现和 Dijkstra算法用优先队列来实现相同的地方是,都是 层次 更新到节点的最短距离,
都是将具有最短距离的节点(如果不在队列中)放入队列中
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[2*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]=0;//另节点 1 为源点
   q.push(1);
   while(!q.empty()) 
   {
      cur=q.front();
      q.pop();
      vis[cur]=0;//出队列 
      ++cnt[cur];
      if(cnt[cur]>n-1)//如果不存在负权回路,那么某个节点的最多被更新的次数为 n-1 次 
         return 0;
      for(int e=first[cur]; e!=-1; 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]=1;//放入队列
        } 
        }
   }
   return 1; 
}

int main()
{
   int i;
   cin>>n>>m;
   for(i=1; i<=n; ++i)
     first[i]=-1; 
   for(i=0; 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=2; i<=n; ++i)
       cout<<"1->"<<i<<":"<<dist[i]<<endl; 
   }
   return 0;
}









本文转自 小眼儿 博客园博客,原文链接:http://www.cnblogs.com/hujunzheng/p/3781817.html,如需转载请自行联系原作者
目录
打赏
0
0
0
0
235
分享
相关文章
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
198 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
内网监控管理软件:PHP 语言队列算法揭秘
在数字化办公环境中,内网监控管理软件对企业的稳定运行和信息安全至关重要。本文深入介绍PHP中的队列算法及其在内网监控软件中的应用,包括监控数据收集、任务调度和日志记录等场景,通过代码示例展示其实现方法。队列算法可提高性能、保证数据顺序并实现异步处理,为企业提供高效的安全保障。
36 1
企业局域网监控软件中 Java 优先队列算法的核心优势
企业局域网监控软件是数字化时代企业网络安全与高效运营的基石,犹如一位洞察秋毫的卫士。通过Java实现的优先队列算法,它能依据事件优先级排序,确保关键网络事件如异常流量、数据泄露等被优先处理,保障系统稳定与安全。代码示例展示了如何定义网络事件类并使用PriorityQueue处理高优先级事件,尤其在面对疑似风险时迅速启动应急措施。这一核心技术助力企业在复杂网络环境中稳健前行,护航业务腾飞。
80 32
【狂热算法篇】探秘图论之Dijkstra 算法:穿越图的迷宫的最短路径力量(通俗易懂版)
【狂热算法篇】探秘图论之Dijkstra 算法:穿越图的迷宫的最短路径力量(通俗易懂版)
2024重生之回溯数据结构与算法系列学习之栈和队列精题汇总(10)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第3章之IKUN和I原达人之数据结构与算法系列学习栈与队列精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列
这篇文章主要介绍了稀疏数组和队列的概念、应用实例以及如何使用数组模拟队列和环形队列的实现方法。
72 0
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列
基于和声搜索优化算法的机器工作调度matlab仿真,输出甘特图
本程序基于和声搜索优化算法(Harmony Search, HS),实现机器工作调度的MATLAB仿真,输出甘特图展示调度结果。算法通过模拟音乐家即兴演奏寻找最佳和声的过程,优化任务在不同机器上的执行顺序,以最小化完成时间和最大化资源利用率为目标。程序适用于MATLAB 2022A版本,运行后无水印。核心参数包括和声记忆大小(HMS)等,适应度函数用于建模优化目标。附带完整代码与运行结果展示。

热门文章

最新文章

下一篇
oss创建bucket