【图论之多源最短路】多源最短路专题(弗洛伊德算法)
注:弗洛伊德算法也可以在数据范围很小时(\(10^2\)级别)求单源最短路,例如3488.最短路径。优点是弗洛伊德算法相对于Dijkstra更好写,就三个for循环,代码比较短,缺点是只有在数据范围是\(10^2\)级别才能用。
3488. 最短路径
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 110, MOD = 100000, INF = 0x3f3f3f3f;
int n, m;
int p[N];
int d[N][N];
int find(int x)
{
if(p[x] != x) p[x] = find(p[x]);
return p[x];
}
int main()
{
cin >> n >> m;
for(int i = 0; i < n; i ++ ) p[i] = i;
memset(d, 0x3f, sizeof d);
for(int i = 0; i < n; i ++ ) d[i][i] = 0;
for(int i = 0, len = 1; i < m; i ++, len = len * 2 % MOD)
{
int a, b;
cin >> a >> b;
if(find(a) != find(b))
{
p[find(a)] = find(b);
d[a][b] = d[b][a] = len;
}
}
for(int k = 0; k < n; k ++ )
for(int i = 0; i < n; i ++ )
for(int j = 0; j < n; j ++ )
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
for(int i = 1; i < n; i ++ )
if(d[0][i] == INF) puts("-1");
else cout << d[0][i] % MOD << endl;
return 0;
}
附堆优化Dijkstra解法
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int N = 110, M = 500 * 2 + 10, mod = 100000;
int n, m, id;
int h[N], e[M], ne[M], w[M], idx;
int dist[N];
int p[N];
bool st[N];
void add(int a, int b, int c)
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
LL qmi(LL a, int k)
{
LL res = 1;
while (k)
{
if (k & 1) res = res * a % mod;
k >>= 1;
a = a * a % mod;
}
return res;
}
void dijkstra()
{
memset(dist, 0x3f, sizeof dist);
dist[0] = 0; // 点的标号从0开始
priority_queue<PII, vector<PII>, greater<PII>> heap;
heap.push({0, 0}); // 第二位是点的编号,第一位是距离
while (heap.size())
{
PII t = heap.top();
heap.pop();
int ver = t.second, distance = t.first;
if (st[ver]) continue;
st[ver] = true;
for (int i = h[ver]; i != -1; i = ne[i])
{
int j = e[i];
if (dist[j] > distance + w[i])
{
dist[j] = distance + w[i];
heap.push({dist[j], j});
}
}
}
}
int main()
{
scanf("%d%d", &n, &m);
memset(h, -1, sizeof h);
for (int i = 0; i < n; i ++ ) p[i] = i;
while (m -- )
{
int a, b;
scanf("%d%d", &a, &b);
int c = qmi(2, id);
id ++ ;
if (find(a) != find(b))
{
p[find(a)] = find(b);
add(a, b, c);
add(b, a, c);
}
}
dijkstra();
for (int i = 1; i < n; i ++ )
{
if (dist[i] == 0x3f3f3f3f) puts("-1");
else printf("%d\n", dist[i] % mod);
}
return 0;
}