题目链接
题目大意:给出一张无向连通图,求起点S到终点E经过k条边的最短路。
数据范围小,可以用Floyd。
利用矩阵相乘,每次下面操作,求出从i到j经过2条边的最短路,连续k次便可以求出经过k边的最短路。
mt floyd(mt x,mt y){
mt ans;
for(int i=1;i<=cnt;i++)
for(int j=1;j<=cnt;j++)
for(int k=1;k<=cnt;k++)
ans.a[i][j]=min(ans.a[i][j],x.a[i][k]+y.a[k][j]);
return ans;
}
但同时一次次乘复杂度过高,可以用快速幂优化。
同时题中的l和r可以用离散化处理(map或干脆建个数值)。
int n,s,t,e,cnt,b[25000];
struct mt{
int a[250][250];
mt(){ memset(a,inf,sizeof(a)); }
};
mt floyd(mt x,mt y){
mt ans;
for(int i=1;i<=cnt;i++)
for(int j=1;j<=cnt;j++)
for(int k=1;k<=cnt;k++)
ans.a[i][j]=min(ans.a[i][j],x.a[i][k]+y.a[k][j]);
return ans;
}
mt qpow(mt x,int k){
mt ans=x;
while(k){
if(k&1) ans=floyd(ans,x);
k>>=1; x=floyd(x,x);
}
return ans;
}
int main(){
n=read(); t=read(); s=read(); e=read(); mt sz;
while(t--){
int u,v,w; w=read(); u=read(); v=read();
if(!b[u]) b[u]=++cnt;
if(!b[v]) b[v]=++cnt;
if(sz.a[b[u]][b[v]]>w) sz.a[b[u]][b[v]]=sz.a[b[v]][b[u]]=w;
}
sz=qpow(sz,n-1);
printf("%d\n",sz.a[b[s]][b[e]]);
}