给定一张由T条边构成的无向图,点的编号为1~1000之间的整数。
求从起点S到终点E恰好经过N条边(可以重复经过)的最短路。
输入格式
第1行:包含四个整数N,T,S,E。
第2…T+1行:每行包含三个整数,描述一条边的边长以及构成边的两个点的编号。
输出格式
输出一个整数,表示最短路的长度。
数据范围
2≤T≤100,
2≤N≤106
输入样例:
2 6 6 4
11 4 6
4 4 8
8 4 9
6 6 8
2 6 9
3 8 9
输出样例:
10
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 205 ;
struct node
{
int mat[maxn][maxn] ;
}A , ans;
int Hash[1100] ;
int cnt = 0 ;
const int INF = 0x3f3f3f3f ;
int N , T , S , E ;
void init()
{
for(int i = 0 ;i < maxn ;i ++)
for(int j = 0 ;j < maxn ;j ++)
A.mat[i][j] = INF ,
ans.mat[i][j] = INF ;
memset(Hash , 0 , sizeof Hash) ;
cnt = 0 ;
return ;
}
node floyd(node a , node b)
{
node res ;
for(int i = 1 ;i <= cnt ;i ++)
for(int j = 1 ;j <= cnt ;j ++)
res.mat[i][j] = INF ;
for(int i = 1 ;i <= cnt ;i ++)
{
for(int j = 1 ;j <= cnt ;j ++)
for(int k = 1 ; k <= cnt ;k ++)
if(res.mat[j][k] > a.mat[j][i] + b.mat[i][k])
res.mat[j][k] = a.mat[j][i] + b.mat[i][k] ;
}
return res ;
}
void qmi(int n)
{
while(n)
{
if(n & 1) ans = floyd(ans , A) ;
A = floyd(A , A) ;
n >>= 1 ;
}
return ;
}
int main()
{
scanf("%d%d%d%d" , &N , &T , &S , &E) ;
init() ;
for(int i =1 ;i <= T ;i ++)
{
int a , b , z ;
scanf("%d%d%d" , &z , &a , &b) ;
// 离散化
if(Hash[a]) a = Hash[a] ;
else a = Hash[a] = ++ cnt ;
if(Hash[b]) b = Hash[b] ;
else b = Hash[b] = ++ cnt ;
A.mat[a][b] = A.mat[b][a] = min(A.mat[a][b] , z) ;
}
// i 到i肯定是0 , 其他的都是INF
for(int i = 1 ;i <= cnt ;i ++) ans.mat[i][i] = 0 ;
qmi(N) ;
cout << ans.mat[Hash[S]][Hash[E]] << endl ;
return 0 ;
}