/*
求解单源最短路问题: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 }