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;
}

目录
相关文章
|
存储 机器学习/深度学习 算法
算法之【动态规划】详解(python)
算法之【动态规划】详解(python)
算法之【动态规划】详解(python)
|
存储 关系型数据库 MySQL
存储过程之五—条件和异常处理
  异常处理可用在子程序中的一般流程控制。当我们希望对sql执行过程中出现的错误情况进行处理,就可以用到异常处理。如针对存储过程 、触发器或函数内部语句可能发生的错误或警告信息,需要进行相关异常或称异常的捕获,然后作出相应的处理。
1344 0
|
5天前
|
搜索推荐 编译器 Linux
一个可用于企业开发及通用跨平台的Makefile文件
一款适用于企业级开发的通用跨平台Makefile,支持C/C++混合编译、多目标输出(可执行文件、静态/动态库)、Release/Debug版本管理。配置简洁,仅需修改带`MF_CONFIGURE_`前缀的变量,支持脚本化配置与子Makefile管理,具备完善日志、错误提示和跨平台兼容性,附详细文档与示例,便于学习与集成。
305 116
|
20天前
|
域名解析 人工智能
【实操攻略】手把手教学,免费领取.CN域名
即日起至2025年12月31日,购买万小智AI建站或云·企业官网,每单可免费领1个.CN域名首年!跟我了解领取攻略吧~
|
7天前
|
数据采集 人工智能 自然语言处理
Meta SAM3开源:让图像分割,听懂你的话
Meta发布并开源SAM 3,首个支持文本或视觉提示的统一图像视频分割模型,可精准分割“红色条纹伞”等开放词汇概念,覆盖400万独特概念,性能达人类水平75%–80%,推动视觉分割新突破。
503 45
Meta SAM3开源:让图像分割,听懂你的话
|
14天前
|
安全 Java Android开发
深度解析 Android 崩溃捕获原理及从崩溃到归因的闭环实践
崩溃堆栈全是 a.b.c?Native 错误查不到行号?本文详解 Android 崩溃采集全链路原理,教你如何把“天书”变“说明书”。RUM SDK 已支持一键接入。
695 222
|
2天前
|
Windows
dll错误修复 ,可指定下载dll,regsvr32等
dll错误修复 ,可指定下载dll,regsvr32等
135 95