Files
python/TangDou/AcWing_TiGao/T3/Floyd/345.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

62 lines
2.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <bits/stdc++.h>
using namespace std;
const int N = 205;
unordered_map<int, int> id;
int s, e; // 起点 终点
int n, m; // 离散化后的节点号 m条边
int k; // 恰好k条边
int g[N][N]; // 图
int f[N][N]; // 最短距离
// 矩阵乘法
void mul(int a[][N], int b[][N]) {
int t[N][N];
memset(t, 0x3f, sizeof t);
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
t[i][j] = min(t[i][j], a[i][k] + b[k][j]);
memcpy(a, t, sizeof t);
}
// 快速幂
void qmi() {
// 使用拷贝矩阵后需要执行k-1次幂
// 解释:拷贝过来原始距离数组g,相当于计算出了两个点(i,j)之间经过一条边后的最短距离;
// 如果再乘一个矩阵g,表示又多经过了一条边,也就是两条边,此时发现,其实最终是k-1次乘g
memcpy(f, g, sizeof f);
k--;
while (k) {
if (k & 1) mul(f, g); // 矩阵快速幂
mul(g, g);
k >>= 1;
}
}
int main() {
scanf("%d %d %d %d", &k, &m, &s, &e);
// 起点的离散化后号为1
id[s] = ++n;
// 如果e与s不同,那么e的新号为2,否则为1
if (!id.count(e)) id[e] = ++n; // 注意这个起点与终点一样的坑
// 重新对s和e给定新的号码
s = id[s], e = id[e];
// 初始化邻接矩阵
memset(g, 0x3f, sizeof g);
while (m--) {
int a, b, c;
scanf("%d %d %d", &c, &a, &b);
if (!id.count(a)) id[a] = ++n; // 记录点的映射关系a-> id[a]
if (!id.count(b)) id[b] = ++n; // 记录点的映射关系b-> id[b]
a = id[a], b = id[b]; // 对a,b给定新的号码
// 利用新的号码将边长c记录到邻接矩阵中
g[a][b] = g[b][a] = min(g[a][b], c);
}
// 快速幂+动态规划思想
qmi();
// 输出从起点到终点,恰好经过k条边的最短路径
printf("%d\n", f[s][e]);
return 0;
}