题意
题解
设从
u
u
u 出发,到
v
v
v 的长度为
k
k
k 的最短路径为
G
k
[
u
]
[
v
]
G_k[u][v]
Gk[u][v],修改
F
l
o
y
d
Floyd
Floyd 算法,则有
G
k
1
+
k
2
[
u
]
[
v
]
=
min
1
≤
w
≤
V
(
G
k
1
[
u
]
[
w
]
+
G
k
2
[
w
]
[
v
]
)
G_{k_1+k_2}[u][v]=\min\limits_{1\leq w\leq V}(G_{k_1}[u][w]+G_{k_2}[w][v])
Gk1+k2[u][v]=1≤w≤Vmin(Gk1[u][w]+Gk2[w][v]) 用矩阵快速幂求解。初始化矩阵时,
G
1
G_1
G1 为原图的邻接矩阵,需要注意的是,按照定义,无自环的情况下
G
1
[
u
]
[
u
]
=
i
n
f
G_1[u][u]=inf
G1[u][u]=inf;同理
G
0
[
u
]
[
u
]
=
0
G_0[u][u]=0
G0[u][u]=0。复杂度
O
(
T
3
log
N
)
O(T^3\log N)
O(T3logN)。
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
#define maxt 105
#define maxv 1005
#define inf 0x3f3f3f3f
typedef vector<int> vec;
typedef vector<vec> mat;
int N, T, S, E, A[maxt], B[maxt], L[maxt], nv, cp[maxv];
mat mul(mat &C, mat &D)
{
mat R(C.size(), vec(D[0].size(), inf));
for (int i = 0; i < C.size(); ++i)
for (int k = 0; k < D.size(); ++k)
for (int j = 0; j < D[0].size(); ++j)
R[i][j] = min(R[i][j], C[i][k] + D[k][j]);
return R;
}
mat pow(mat &M, int n)
{
mat R(M.size(), vec(M.size(), inf));
for (int i = 0; i < M.size(); ++i)
R[i][i] = 0;
while (n)
{
if (n & 1)
R = mul(R, M);
M = mul(M, M);
n >>= 1;
}
return R;
}
int main()
{
scanf("%d%d%d%d", &N, &T, &S, &E);
memset(cp, -1, sizeof(cp));
for (int i = 0; i < T; ++i)
{
scanf("%d%d%d", L + i, A + i, B + i);
cp[A[i]] = cp[A[i]] != -1 ? cp[A[i]] : nv++;
cp[B[i]] = cp[B[i]] != -1 ? cp[B[i]] : nv++;
}
mat M(nv, vec(nv, inf));
for (int i = 0; i < T; ++i)
{
int x = cp[A[i]], y = cp[B[i]];
M[x][y] = M[y][x] = L[i];
}
M = pow(M, N);
printf("%d\n", M[cp[S]][cp[E]]);
return 0;
}