题目大意:起点到终点经过边的数目为k的最短路值为多少。


离散数学的定理:

01邻接矩阵A的K次方C=A^K,C[i][j]表示i点到j点正好经过K条边的路径数


对应于这道题,对邻接图进行K次floyd之后,C[i][j]就是点i到j正好经过K条边的最短路。

但是每次floyd的复制度十分大,所以我们需要使用矩阵快速幂。


AC代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=210,inf=0x3f3f3f3f;
int n,t,s,e,cnt,g[N][N],a[N][N];
unordered_map<int,int> mp;
void mul(int a[][N],int b[][N]){
	int p[N][N]; memset(p,inf,sizeof p);
	for(int k=1;k<=cnt;k++)
		for(int i=1;i<=cnt;i++)
			for(int j=1;j<=cnt;j++)
				p[i][j]=min(p[i][j],a[i][k]+b[k][j]);
	for(int i=1;i<=cnt;i++)	for(int j=1;j<=cnt;j++)	a[i][j]=p[i][j];
}
void qmi(int b){
	for(int i=1;i<=cnt;i++)	for(int j=1;j<=cnt;j++)	a[i][j]=g[i][j];
	while(b){
		if(b&1)	mul(g,a); b>>=1; mul(a,a);
	}
}
signed main(){
	cin>>n>>t>>s>>e;	memset(g,inf,sizeof g);
	while(t--){
		int u,v,w;	cin>>w>>u>>v;
		if(!mp[u])	mp[u]=++cnt;
		if(!mp[v])	mp[v]=++cnt;
		g[mp[u]][mp[v]]=g[mp[v]][mp[u]]=min(g[mp[u]][mp[v]],w);
	}
	qmi(n-1);
	cout<<g[mp[s]][mp[e]]<<endl;
	return 0;
}