• SPFA算法(求解单源最短路)详解 + 最短路 之 CODE[VS] 1079 回家


    /*
    求解单源最短路问题:SPFA算法(有向加权图不存在负权回路)
     
    参考:《数据结构与编程实验--大学生程序设计课程与竞赛训练教材》(http://book.douban.com/subject/10537877/)
     
    弥补Dijkstra算法无法处理图中存在负权边;
    弥补Bellman-Ford算法效率低。
     
    SPFA算法类似宽度优先搜索,动态逼近法:
    	队列Q存储可以优化其他节点的节点,每次从队列中取出队首节点u,并用u点的dist值对
    	u点出边所指向的节点v进行松弛操作。如果v点的dist值有所调整且v点不在队列Q中,则
    	v点进入队列Q。
    	这样不断从队列Q中取出节点来进行松弛操作,直至Q队列为空。
     
    时间复杂度:
    	在算法执行时,设k为所有节点入队的平均次数(可以证明k一般小于等于2),而每个节点
    	入队后需要花费O(|E|)时间对它们的所有出边进行松弛操作,
    	故时间复杂度:O(k*|E|)
     
    对比Bellman-Ford算法:
    	相似之处(思想):
    		计算过程都是迭代式的,最短路径都是临时的,都采用了不断逼近最优解的贪心策略,
    		只有最后一步才确定想要的结果。
    	不同之处(实现方式):
    		Bellman-Ford算法:某个点最短路径估计值被更新了,那就必须对所有边的尾做一次松弛操作;
    		SPFA算法:某个点最短路径估计值被更新了,仅需对该点出边的端点做一次松弛操作。
     
    ----------------------------------------
    CODE[VS] 1079 回家
     
    从'Z'出发,最短路Spfa即可。
     
    */
      1 #include <iostream>
      2 #include <cstdlib>
      3 #include <cstdio>
      4 #include <cstddef>
      5 #include <iterator>
      6 #include <algorithm>
      7 #include <string>
      8 #include <locale>
      9 #include <cmath>
     10 #include <vector>
     11 #include <cstring>
     12 #include <map>
     13 #include <utility>
     14 #include <queue>
     15 #include <stack>
     16 #include <set>
     17 #include <functional>
     18 using namespace std;
     19 typedef pair<int, int> P; 
     20 const int INF = 0x3f3f3f3f;
     21 const int modPrime = 3046721;
     22 const double eps = 1e-9;
     23 const int MaxN = 60;
     24 
     25 int n;
     26 
     27 struct Edge
     28 {
     29     int to;
     30     int dis;
     31 };
     32 
     33 vector<Edge> edgeVec[MaxN];
     34 int dis[MaxN];
     35 
     36 int charToNum(char ch)
     37 {
     38     if (ch >= 'A' && ch <= 'Z')
     39     {
     40         // 0~25
     41         return (ch - 'A');
     42     }
     43     else
     44     {
     45         // 26~51
     46         return (ch - 'a') + 26;
     47     }
     48 }
     49 
     50 char numToChar(int num)
     51 {
     52     if (num >= 0 && num <= 25)
     53     {
     54         // 0~25
     55         return ('A' + num);
     56     }
     57     else
     58     {
     59         // 26~51
     60         return ('a' + (num - 26));
     61     }
     62 }
     63 
     64 
     65 void Spfa()
     66 {
     67     fill(dis, dis + MaxN, INF);
     68     int S = charToNum('Z');
     69     dis[S] = 0;
     70 
     71     bool isInQue[MaxN];
     72     fill(isInQue, isInQue + MaxN, false);
     73 
     74     queue<int> que;
     75     que.push(S);
     76     isInQue[S] = true;
     77     while (!que.empty())
     78     {
     79         int node = que.front();
     80         que.pop();
     81         isInQue[node] = false;
     82         Edge eg;
     83         for (int i = 0; i < edgeVec[node].size(); ++i)
     84         {
     85             eg = edgeVec[node][i];
     86             if (dis[eg.to] > dis[node] + eg.dis)
     87             {
     88                 dis[eg.to] = dis[node] + eg.dis;
     89                 if (!isInQue[eg.to])
     90                 {
     91                     que.push(eg.to);
     92                     isInQue[eg.to] = true;
     93                 }
     94             }
     95         }
     96     }
     97 }
     98 
     99 void Solve()
    100 {
    101     Spfa();
    102     int num = 0;
    103     int ans = INF;
    104     for (int i = 0; i < 25; ++i)
    105     {
    106         if (ans > dis[i])
    107         {
    108             num = i;
    109             ans = dis[i];
    110         }
    111     }
    112     cout << numToChar(num) << " " << ans << endl;
    113 }
    114 
    115 int main()
    116 {
    117 #ifdef HOME
    118     freopen("in", "r", stdin);
    119     //freopen("out", "w", stdout);
    120 #endif
    121 
    122     cin >> n;
    123     Edge eg;
    124     for (int i = 0; i < n; ++i)
    125     {
    126         char chFrom, chTo;
    127         cin >> chFrom >> chTo >> eg.dis;
    128 
    129         int ifrom = charToNum(chFrom);
    130         int ito = charToNum(chTo);
    131 
    132         eg.to = ito;
    133         edgeVec[ifrom].push_back(eg);
    134         eg.to = ifrom;
    135         edgeVec[ito].push_back(eg);
    136     }
    137     Solve();
    138 
    139 #ifdef HOME
    140     cerr << "Time elapsed: " << clock() / CLOCKS_PER_SEC << " ms" << endl;
    141     _CrtDumpMemoryLeaks();
    142 #endif
    143     return 0;
    144 }
    
    
    
     
  • 相关阅读:
    Vue+element UI实现“回到顶部”按钮组件
    JS判断字符串长度的5个方法(区分中文和英文)
    从vue源码看Vue.set()和this.$set()
    mac下git安装与使用
    JS数组reduce()方法详解及高级技巧
    vue中router.go、router.push和router.replace的区别
    上传及更新代码到github(以及如何在vscode上提交自己的代码)
    VSCode打开多个项目文件夹的解决方法
    get请求和post请求的区别
    android 进程的优先级
  • 原文地址:https://www.cnblogs.com/shijianming/p/5034838.html
Copyright © 2020-2023  润新知