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 }


 
原文地址:https://www.cnblogs.com/shijianming/p/5034838.html