题意:
已知起点 s 与终点 e,要求走 N 条边的最短路。
思路:
应用动态规划的思维。
邻接矩阵上的乘法,应用快速幂。
参考论文:*俞华程《矩阵乘法在信息学中的应用》
PS:
网上解题报告看过很多,但我觉得推导中都偏重与 floyd 算法。
论文里邻接矩阵乘法的内容,很好的解释了,为什么答案是一个矩阵连乘的结果。
纪念一下这道题。
/*
无向图,已知起点和终点,要求走严格 N 条边的最短路。
点数 <= 200
N <= 1000000
邻接矩阵上的乘法,应用快速幂。
*俞华程《矩阵乘法在信息学中的应用》
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 110;
struct M{
int mm[maxn][maxn];
M()
{
memset( mm, -1, sizeof(mm) );
}
}mat, tmat;
int cnt, f[1000010];
int k, m, s, e;
int min( int a, int b ){ return a < b ? a : b; }
void init()
{
memset( f, 0, sizeof(f) );
cnt = 0;
}
M matMul( M mat, M tmat )
{
M temp;
int i, j, t;
for( i = 1; i <= cnt; i++ )
{
for( j = 1; j <= cnt; j++ )
{
for( t = 1; t <= cnt; t++ )
{
if( tmat.mm[t][j] != -1 && mat.mm[i][t] != -1
&& ( temp.mm[i][j] == -1 || temp.mm[i][j] > mat.mm[i][t] + tmat.mm[t][j] ) )
temp.mm[i][j] = mat.mm[i][t] + tmat.mm[t][j];
}
}
}
return temp;
}
int main()
{
scanf( "%d%d%d%d", &k, &m, &s, &e );
int i, u, v, w;
init();
for( i = 0; i < m; i++ )
{
scanf( "%d%d%d", &w, &u, &v );
if( !f[u] )f[u] = ++cnt;
if( !f[v] )f[v] = ++cnt;
tmat.mm[f[u]][f[v]] = tmat.mm[f[v]][f[u]] = w;
}
int num = 0;
while( k )
{
if( k & 1 )
{
if( !num )
{
mat = tmat;
num = 1;
}
else mat = matMul( mat, tmat );
}
tmat = matMul( tmat, tmat );
k >>= 1;
}
printf( "%d\n", mat.mm[f[s]][f[e]] );
return 0;
}