*题解:P6190 [NOI Online #1 入门组] 魔法
解析
考虑 \(k = 0\) 的情况,是一个裸的最短路,跑一遍 Floyd 即可。
考虑 \(k = 1\) 的情况,我们枚举需要取反边权的边 \(u\to v\),那么取反该边情况下 \(1\) 至 \(n\) 的最短路其实就是 \(1\to u\),\(v \to n\) 两部分最短路和我们取反后的这条边并起来。具体地,设 \(d_{i,j}\) 表示原图中 \(i\) 到 \(j\) 的最短路,\(u,v\) 边权为 \(w\),那么至多取反一次的最短路为 \(f_{i,j} = \min (d_{i,u} -w + d_{v,j})\)。
考虑 \(k = 2\) 的情况,可以枚举点然后转化成 \(k = 1\) 的情况,具体地,至多取反两次后的最短路为 \(g_{i,j} = \min(f_{i,x} + f_{x,j})\)。
同理,如果设 \(d_{i,u,v}\) 表示至多取反 \(i\) 次之后,\(u\) 到 \(v\) 的最短路,那么对于 \(i > 1\),有:
\[d_{i,u,v} = \min (d_{i - 1,u,x} + d_{1,x,v})
\]
这是 \((\min,+)\) 矩阵乘法的形式,可以进行矩阵加速。
时间复杂度 \(O(n^2m + n^3 \log k)\)。
代码
#include <bits/stdc++.h>
#define eps 0.0000000001
#define ls(x) ((x) << 1)
#define rs(x) (((x) << 1) | 1)
#define mid ((l + r) >> 1)
using namespace std;
typedef long long ll;
typedef unsigned ui;
typedef pair<int,int> pii;
const int N = 100 + 5,M = 20,P = 2000000,mod = 998244353,mod2 = 1e9 + 7,b1 = 131,b2 = 13331;
ll d[N][N];
struct Edge{
int u,v;
ll w;
};
vector<Edge> e;
struct Mtx{
ll m[N][N];
int row,col;
Mtx (int r,int c) : row(r),col(c){
for(int i=1;i<=row;i++){
for(int j=1;j<=col;j++){
m[i][j] = 1e18;
}
}
}
Mtx operator * (Mtx b){
Mtx c(row,b.col);
for(int i=1;i<=c.row;i++){
for(int j=1;j<=c.col;j++){
for(int k=1;k<=col;k++){
c.m[i][j] = min({c.m[i][j],m[i][k] + b.m[k][j]});
}
}
}
return c;
}
void print(){
cout<<"_______________________\n";
for(int i=1;i<=row;i++){
for(int j=1;j<=col;j++){
cout<<(m[i][j] > 1e17 ? -1 : m[i][j])<<" \n"[j==col];
}
cout<<'\n';
}
cout<<"_______________________\n";
}
};
Mtx I(int r){
Mtx res(r,r);
for(int i=1;i<=r;i++){
res.m[i][i] = 0;
}
return res;
}
Mtx qmi(Mtx a,int b){
Mtx res = I(a.row);
while(b){
if(b & 1) res = res * a;
b >>= 1;
a = a * a;
}
return res;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int n,m,k;
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i != j){
d[i][j] = 1e18;
}
}
}
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
e.push_back({u,v,w});
d[u][v] = w;
}
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
d[i][j] = min(d[i][j],d[i][k] + d[k][j]);
}
}
}
Mtx a = I(n);
for(int i=0;i<e.size();i++){
int u = e[i].u,v = e[i].v,w = e[i].w;
for(int j=1;j<=n;j++){
for(int k=1;k<=n;k++){
a.m[j][k] = min(a.m[j][k],d[j][u] + d[v][k] - w);
}
}
}
if(k){
a = qmi(a,k);
cout<<a.m[1][n];
}else{
cout<<d[1][n];
}
return 0;
}

浙公网安备 33010602011771号