赞
踩
链接:920. 最优乘车
相关:[Hbfs] lc815. 公交路线(建图+多源bfs+bfs最短路+思维+好题)
关于 spfa 循环队列初始化问题:
以为和 [Hbfs] lc815. 公交路线(建图+多源bfs+bfs最短路+思维+好题) 是一样的题…
然而写完后疯狂报错:发现本题的公交线路是单向的,终点不能到起点。
而力扣是循环的,终点可以到起点。
力扣的建图方式是无向图,显然就不对了…
建图方式:
则从起点 1 到终点 n,由于图中权值均为 1,那么就可以直接 bfs 即可。
其实如果不这样建图填边的话,本题图中权值只有 0、1 两种,即在同一个线路中跑,跑到别的线路中去,采用双端队列广搜也未尝不可。
可是,我还是想完成,力扣 815. 公交路线 的看环成点的写法…
使用邻接矩阵+朴素 bfs
做了,使用链式前向星+spfa
做了。虽然 spfa
已死,但是依旧很香。
值得注意的是,最短路算法本身和存图方式是无关的。spfa+邻接矩阵的操作也是完全可以的,但是我没这样写过。应该不难。
时间复杂度: O ( n 2 ) O(n^2) O(n2)
空间复杂度: O ( n 2 ) O(n^2) O(n2)
y总代码,朴素 bfs+邻接矩阵:
#include <iostream> #include <cstring> #include <algorithm> #include <sstream> using namespace std; const int N = 505; int m, n; bool g[N][N]; int dist[N]; int stop[N]; bool st[N]; int q[N]; void bfs() { memset(dist, 0x3f, sizeof dist); int hh = 0, tt = 0; q[0] = 1, dist[1] = 0; while (hh <= tt) { int t = q[hh ++ ]; for (int i = 1; i <= n; i ++ ) { if (g[t][i] && dist[i] > dist[t] + 1) { dist[i] = dist[t] + 1; q[ ++ tt] = i; } } } } int main() { scanf("%d%d", &m, &n); string s; getline(cin, s); while (m -- ) { getline(cin, s); stringstream scin(s); int cnt = 0, x; while (scin >> x) stop[cnt ++ ] = x; for (int i = 0; i < cnt; i ++ ) for (int j = i + 1; j < cnt; j ++ ) g[stop[i]][stop[j]] = true; } bfs(); if (dist[n] == 0x3f3f3f3f) puts("NO"); else printf("%d\n", dist[n] - 1); return 0; }
spfa+链式前向星
#include <iostream> #include <cstring> #include <algorithm> #include <sstream> using namespace std; const int N = 505, M = 1000005; int m, n; int h[N], e[M], ne[M], idx; int dist[N]; bool st[N]; int stop[N]; int q[N]; void add(int a, int b) { e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ; } void spfa() { memset(dist, 0x3f, sizeof dist); int hh = 0, tt = 1; // 杜绝这个二逼写法,要么就 tt=0 可以 // q[tt ++ ] = 1, dist[1] = 0, st[1] = true; q[0] = 1, dist[1] = 0, st[1] = true; while (hh != tt) { auto t = q[hh ++ ]; if (hh == N) hh = 0; st[t] = false; for (int i = h[t]; ~i; i = ne[i]) { int j = e[i]; if (dist[j] > dist[t] + 1) { dist[j] = dist[t] + 1; if (!st[j]) { st[j] = true; q[tt ++ ] = j; } } } } } int main() { scanf("%d%d", &m, &n); string s; getline(cin, s); memset(h, -1, sizeof h); while (m -- ) { getline(cin, s); stringstream scin(s); int cnt = 0, x; while (scin >> x) stop[cnt ++ ] = x; for (int i = 0; i < cnt; i ++ ) for (int j = i + 1; j < cnt; j ++ ) { int a = stop[i], b = stop[j]; add(a, b); } } spfa(); if (dist[n] == 0x3f3f3f3f) puts("NO"); else printf("%d\n", dist[n] - 1); return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。