首先,我们要明确这里的最短路是在经过n条路径的前提下的最短路,因为这是无向图,所以一定有解。
我们先来看朴素的Floyd的代码:
for(int k = 1; k <= n; k++)
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
f[i][j] = min(f[i][j],f[i][k] + f[k][j]);
其中,我们每次都是枚举k并用ta去当中转点去更新每一个i->j的最短路。
那么,当k等于n/2时这段代码完成了什么呢?
那就是我们尝试了用[1,n/2]的点去更新最短路,我们可以发现,这样得到的最短路最多包含k+1条路径。
为什么是最多k+1条呢?
因为我们每次用k去尝试更新i->j的最短路是不一定成功(即f[i][j]<=f[i][k]+f[k][j])
所以我们可以用Floyd+dp+倍增去切掉这道题
我们再来看一下矩阵乘法的代码:
for(int k = 1; k <= n; k++)
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
c[i][j] = c[i][j] + a[i][k] * b[k][j];
是不是和Floyd的代码有点相似?
因为我们要求的是最短路,所以我们要对这个矩阵乘法魔改一下:
memset(c,0x7f,sizeof(c));
for(int k = 1; k <= n; k++)
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
c[i][j] = min(c[i][j],a[i][k] + a[k][j]);
是不是和Floyd越来越相似了……
但是在这里,c[i][j]的初值为INF,所以我们每次枚举k都会选择一条边去更新最短路,所以如果我们用邻接矩阵map(不是STL的那个map)去存边,那么map的n次方存的就是经过n条边的最短路。
code:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define ll long long
#define INF 0x7fffffff
#define re register
#define rep(i,a,b) for(int i = (a); i <= (b); i++)
#define qwq printf("qwq\n");
using namespace std;
long long read()
{
register long long x = 0,f = 1;register char ch;
ch = getchar();
while(ch > '9' || ch < '0'){if(ch == '-') f = -f;ch = getchar();}
while(ch <= '9' && ch >= '0'){x = x * 10 + ch - 48;ch = getchar();}
return x * f;
}
long long n,m,t,sta,End,cnt,siz,u,d[100005];
struct edge{
int fro,to,l;
}e[100005];
struct juzhen{
long long a[105][105];
juzhen operator * (const juzhen &x) const
{
juzhen c;
memset(c.a,0x7f,sizeof(c.a));
for(int k = 1; k <= siz; k++)
for(int i = 1; i <= siz; i++)
for(int j = 1; j <= siz; j++)
c.a[i][j] = min(c.a[i][j],a[i][k]+x.a[k][j]);
return c;
}
}ans,map;
void ksm(int b)
{
while(b > 0)
{
if(b & 1) ans = ans * map;
map = map * map;
b >>= 1;
}
}
bool cmp(int a,int b){return a < b;}
int main()
{
n = read(); m = read(); sta = read(); End = read();
for(int i = 1; i <= m; i++)
{
e[i].l = read(); e[i].fro = read(); e[i].to = read();
d[++cnt] = e[i].fro; d[++cnt] = e[i].to;
}
sort(d + 1, d + cnt + 1, cmp);
siz = unique(d + 1, d + cnt + 1) - d - 1;
for(int i = 1; i <= siz; i++)
for(int j = 1; j <= siz; j++)
map.a[i][j] = INF;
for(int i = 1; i <= m; i++)
{
e[i].fro = lower_bound(d + 1, d + siz + 1, e[i].fro) - d;
e[i].to = lower_bound(d + 1, d + siz + 1, e[i].to) - d;
map.a[e[i].fro][e[i].to] = e[i].l;
map.a[e[i].to][e[i].fro] = e[i].l;
}
sta = lower_bound(d + 1, d + siz + 1, sta) - d;
End = lower_bound(d + 1, d + siz + 1, End) - d;// li san hua
for(int i = 1; i <= siz; i++)
for(int j = 1; j <= siz; j++)
ans.a[i][j] = map.a[i][j];
ksm(n - 1);
printf("%d\n",ans.a[sta][End]);
return 0;
}