zoukankan      html  css  js  c++  java
  • Dijkstra算法2

      1 // 再来一手精髓的Dijkstra
      2 // 复杂度O( E*log(V) )
      3 
      4 #include <cstdio>
      5 #include <iostream>
      6 #include <vector>
      7 #include <queue>
      8 
      9 using namespace std;
     10 
     11 const int max_N = 1000+2;
     12 const int max_E = 10000+2;
     13 const int INF = 1e9;
     14 
     15 int N,E;
     16 int d[max_N];
     17 
     18 // 来自何方,已经不重要了。
     19 // 实际上是在邻接表实现的过程中,行号即为来自的顶点
     20 struct edge
     21 {
     22     int to,cost;
     23 };
     24 // P.first代表距离,P.second代表顶点编号
     25 typedef pair<int,int> P;
     26 
     27 vector<edge> G[max_N];
     28 
     29 // 这一个算法下来,我们在数组d中得到了从s点到其余所有顶点的最短路程
     30 void dijkstra(int s)
     31 {
     32     // 建立最堆,来维护最小距离,可以降低一层复杂度
     33     priority_queue< P,vector<P>,greater<P> > que;
     34 
     35     fill(d,d+N,INF);
     36     d[s]=0;
     37     que.push(P(0,s));
     38 
     39     while(!que.empty())
     40     {
     41         // 取出一个顶点,看是否是Dijstra算法中,已经确定的最小顶点
     42         P p=que.top();
     43         que.pop();
     44 
     45         int v=p.second;
     46         // 让我们来看看这一步
     47         // 首先,每次取出堆中的最小元素
     48         // 然后去检索这个堆顶元素的标号所对应的距离
     49         // 咦,你会发现堆顶这个距离,竟然比取出的最小元素还要小
     50         // 惊讶?难道出错了?没有,考虑Dijkstra算法的流程,这个顶点肯定是之前已经确定过的最小顶点了,不需要考虑
     51         // 之前的实现是多加了一个flag数组来标记,这里可以省去这部分内存,直接用这个条件来判断
     52         if(d[v]<p.first)
     53         {
     54             continue;
     55         }
     56 
     57         for(int i=0;i<G[v].size();++i)
     58         {
     59             edge e=G[v][i];
     60             if(d[e.to] > d[v] + e.cost)
     61             {
     62                 d[e.to]=d[v]+e.cost;
     63                 // 数组中维护此次被更新的节点即可,其余节点不需要维护
     64                 que.push(P(d[e.to],e.to));
     65             }
     66         }
     67     }
     68 
     69 }
     70 
     71 int main()
     72 {
     73     int a,b,c;
     74     scanf("%d %d",&N,&E);
     75     for(int i=0;i<E;++i)
     76     {
     77         scanf("%d %d %d",&a,&b,&c);
     78         edge e;
     79         e.to=b;
     80         e.cost=c;
     81         G[a].push_back(e);
     82         // 无向图
     83         e.to=a;
     84         e.cost=c;
     85         G[b].push_back(e);
     86     }
     87 
     88     dijkstra(0);
     89 
     90     for(int i=0;i<N;++i)
     91     {
     92         printf("%d ",d[i]);
     93     }
     94 
     95     return 0;
     96 }
     97 
     98 /*
     99 7 10
    100 0 1 2
    101 0 2 5
    102 1 2 4
    103 1 3 6
    104 1 4 10
    105 2 3 2
    106 3 5 1
    107 4 5 3
    108 4 6 5
    109 5 6 9
    110 
    111 
    112 */
  • 相关阅读:
    leetcode(5)-罗马数字转整数
    leetcode(4)-整数反转
    leetcode(3)-回文数
    leetcode(2)-有效的括号
    leetcode(1)-两数之和
    HTTP基础(一)
    ubuntu 18.04安装MariaDB 10.04并通过远程navicat连接
    ubuntu18.04 root用户登录
    xshell连接ubuntu虚拟机
    ubuntu18.04使用node压缩包的安装及配置
  • 原文地址:https://www.cnblogs.com/jishuren/p/12316035.html
Copyright © 2011-2022 走看看