设计状态为走了k步,从i-j的最短路,由于加法满足结合律,因此可以用倍增来优化逼近n
这样可以log复杂度逼近,代码与floyd相似,但是状态的定义完全不同,本题还需要离散化一下,因为原数太大
#include<bits/stdc++.h> using namespace std; const int N=210; int g[N][N]; int res[N][N]; int n,t,s,e; int cnt; void mul(int c[][N],int a[][N],int b[][N]){ int tmp[N][N]; memset(tmp,0x3f,sizeof tmp); int i,j,k; for(k=1;k<=cnt;k++){ for(i=1;i<=cnt;i++){ for(j=1;j<=cnt;j++){ tmp[i][j]=min(tmp[i][j],a[i][k]+b[k][j]); } } } memcpy(c,tmp,sizeof tmp); } void qmi(){ memset(res,0x3f,sizeof res); for(int i=1;i<N;i++) res[i][i]=0; while(n){ if(n&1){ mul(res,res,g); } mul(g,g,g); n>>=1; } } int main(){ memset(g,0x3f,sizeof g); cin>>n>>t>>s>>e; int i; map<int,int> id; cnt=1; if(!id.count(s)) id[s]=cnt++; if(!id.count(e)) id[e]=cnt++; s=id[s]; e=id[e]; for(i=1;i<=t;i++){ int a,b,c; scanf("%d%d%d",&c,&a,&b); if(!id.count(a)) id[a]=cnt++; if(!id.count(b)) id[b]=cnt++; a=id[a],b=id[b]; g[a][b]=g[b][a]=min(g[a][b],c); } cnt--; qmi(); printf("%d\n",res[s][e]); }