最近看了《算法笔记》上面关于最短路径的部分,学习了一种之前没见过的算法:SPFA。
理论上SPFA算法会比Dijkstra快,顾而找了一题测试一下。
使用PAT A1072题,因为这题求最短路径的部分很单纯,没有其他的权,而且测试点的复杂度够高,能够看出时间上的差别。
题目链接
速度对比(重点看测试点4)
Dijkstra速度
SPFA

多次提交对比,Dijkstra算法都在50ms左右,而SPFA一直在10ms左右,可见SPFA确实比Dijkstra快不少,而且思路也不复杂,以后可以多多使用。
代码如下
#include<bits/stdc++.h>#include<unordered_map>using namespace std;#define MAXNODE 1015#define INF 0x3ffffff#define G2index(G) ((n)+(G))#define index2G(index) ((index)-(G))struct Node{int v, dis;//目标与距离};int dis[MAXNODE];int n, m, k, dmax;bool used[MAXNODE], inqueue[MAXNODE];vector<Node> graph[MAXNODE];void Dijkstra(int start){fill(dis, dis + MAXNODE, INF);fill(used, used + MAXNODE, false);dis[start] = 0;for (int i = 0; i < n + m - 1; i++) {int minnode = -1, mindis = INF;for (int j = 1; j <= n + m; j++) {if (!used[j] && dis[j] < mindis) {minnode = j;mindis = dis[j];}}if (minnode == -1)return;used[minnode] = true;int tdis = dis[minnode];for (Node node : graph[minnode]) {if (tdis + node.dis < dis[node.v]) {dis[node.v] = tdis + node.dis;}}}}void SPFA(int start){fill(dis, dis + MAXNODE, INF);fill(inqueue, inqueue + MAXNODE, false);dis[start] = 0;int tdis = 0;queue<int> q;for (Node node : graph[start]) {if (tdis + node.dis < dis[node.v]) {dis[node.v] = node.dis + tdis;q.push(node.v);inqueue[node.v] = true;}}while (!q.empty()) {int nodeid = q.front();q.pop();inqueue[nodeid] = false;for (Node node : graph[nodeid]) {tdis = dis[nodeid];if (tdis + node.dis < dis[node.v]) {dis[node.v] = node.dis + tdis;if (!inqueue[node.v]) {q.push(node.v);inqueue[node.v] = true;}}}}}struct Ans{int Gid, mindis, totaldis;};vector<Ans> ans;void getans(int Gid){int totaldis, mindis;mindis = INF;totaldis = 0;for (int i = 1; i <= n; i++) {if (dis[i] > dmax)return;if (dis[i] < mindis) {mindis = dis[i];}totaldis += dis[i];}ans.push_back(Ans{ Gid,mindis,totaldis });}int main() {scanf("%d%d%d%d", &n, &m, &k, &dmax);for (int i = 0; i < k; i++) {int c1, c2, dd;char cs1[10], cs2[10];scanf("%s%s%d", cs1, cs2, &dd);if (cs1[0] == 'G') {c1 = G2index(atoi(cs1 + 1));}else {c1 = atoi(cs1);}if (cs2[0] == 'G') {c2 = G2index(atoi(cs2 + 1));}else {c2 = atoi(cs2);}graph[c1].push_back(Node{ c2, dd });graph[c2].push_back(Node{ c1, dd });}for (int i = 1; i <= m; i++) {//Dijkstra(G2index(i));SPFA(G2index(i));getans(i);}Ans myans;myans.Gid = -1;myans.totaldis = INF;myans.mindis = 0;for (Ans a : ans) {if (a.mindis > myans.mindis)myans = a;else if (a.mindis == myans.mindis) {if (a.totaldis < myans.totaldis)myans = a;}}if (myans.Gid == -1) {printf("No Solution");return 0;}printf("G%d\n%.1lf %.1lf", myans.Gid, (double)myans.mindis, (double)myans.totaldis / n);return 0;}
代码思路就不写了,大家可以看算法笔记。
