一道很有纪念意义的题目啊qwq
感觉其实还不是很理解。
首先,根据题目的数据范围,我们可以想到用 f l o y d floyd floyd去解决这个问题。
我们会发现,假设我们已经知道了一个经过 x x x条路,到某个点的最短路矩阵 a a a,同时我们知道了每个点出发经过一条路到各个点的最短路矩阵 b b b,我们令 c [ i ] [ j ] = m i n ( c [ i ] [ j ] , a [ i ] [ k ] + b [ k ] [ j ] ) c[i][j]=min(c[i][j],a[i][k]+b[k][j]) c[i][j]=min(c[i][j],a[i][k]+b[k][j]),新得到的矩阵,就应该对应的是经过 x + 1 x+1 x+1条路径到每个点的最短路。
那我们貌似可以通过 k k k次暴力合并,来得到答案。但显然这样的复杂度是不够优秀的。
经过观察,我们发现这个过程很像是两个矩阵在进行矩阵乘法(一种变形)。
那么我们可以直接选择矩阵快速幂来优化这个过程。然后就可以把复杂度变到比较优秀的复杂度辣!
但是需要注意的一个小 t i p s tips tips是,我们可以令初始的 a n s ans ans等于一开始的 d i s dis dis矩阵,然后只需要和 k − 1 k-1 k−1次方的矩阵合并即可。
QWQ
感觉细节还是很多啊
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define mk make_pair
#define ll long long
#define int long long
#define pb push_back
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int maxn = 210;
struct Ju{
int x,y;
int a[maxn][maxn];
Ju operator* (Ju b)
{
Ju ans;
ans.x=x;
ans.y=b.y;
memset(ans.a,127/3,sizeof(ans.a));
for (int k=1;k<=y;k++)
for (int i=1;i<=ans.x;i++)
for (int j=1;j<=ans.y;j++)
ans.a[i][j]=min(ans.a[i][j],a[i][k]+b.a[k][j]);
return ans;
}
};
Ju dis;
Ju qsm(Ju i,int j)
{
Ju ans = i;
while (j)
{
if (j&1) ans=ans*i;
i=i*i;
j>>=1;
}
return ans;
}
int tot;
int x[maxn],y[maxn],w[maxn];
int n,m;
vector<int> v;
int k;
int s,t;
int getnum(int val)
{
return lower_bound(v.begin(),v.end(),val)-v.begin()+1;
}
signed main()
{
k=read();
m=read();
s=read(),t=read();
v.pb(s);
v.pb(t);
for (int i=1;i<=m;i++)
{
w[i]=read(),x[i]=read(),y[i]=read();
v.pb(x[i]);
v.pb(y[i]);
}
sort(v.begin(),v.end());
n=unique(v.begin(),v.end())-v.begin();
v.resize(n);
n++;
s=getnum(s);
t=getnum(t);
memset(dis.a,0x3f,sizeof(dis.a));
//for(int i=1;i<=n;i++) dis.a[i][i]=0;
dis.x=n;
dis.y=n;
for (int i=1;i<=m;i++)
{
x[i]=getnum(x[i]);
y[i]=getnum(y[i]);
dis.a[x[i]][y[i]]=min(dis.a[x[i]][y[i]],w[i]);
dis.a[y[i]][x[i]]=dis.a[x[i]][y[i]];
}
dis=qsm(dis,k-1);
cout<<dis.a[s][t]<<endl;
return 0;
}