題解 POJ3613 【Cow Relays】
阿新 • • 發佈:2020-07-27
題目大意
給你一個具有 \(m\) 條邊的圖( \(2\le m\le 100\) ),詢問兩點之間正好經過 \(k\) 條邊的最短路( \(2\le k\le 1e6\) )。
題解
對於這種正好經過 \(k\) 條邊的問題,使用矩陣快速冪求解。但是這裡的矩陣快速冪需要進行修改,改為 \(C_{ij}=min(A_{ik}+B_{kj})\) 。因為 \(min\) 是滿足結合律的,所以我們的這個新運算也是滿足結合律的,所以我們可以進行矩陣快速冪。
程式碼如下:
#include<cstdio> #include<iostream> #include<cstring> #include<queue> #include<map> #include<algorithm> using namespace std; const int N=1005,M=105; int k,m,f,t; int u[M],v[M],w[M]; int s[M*2],ls; int mp[N]; struct Matrix { int n,m; int h[M*2][M*2]; Matrix() { n=m=0; memset(h,63,sizeof(h)); } }; Matrix operator + (const Matrix a,const Matrix b) { Matrix ans; ans.n=a.n; ans.m=b.m; for(int i=1;i<=a.n;++i) { for(int j=1;j<=b.m;++j) { for(int k=1;k<=a.m;++k) ans.h[i][j]=min(ans.h[i][j],a.h[i][k]+b.h[k][j]); } } return ans; } int main() { cin>>k>>m>>f>>t; for(int i=1;i<=m;++i) { cin>>w[i]>>u[i]>>v[i]; s[++ls]=u[i]; s[++ls]=v[i]; } sort(s+1,s+1+ls); ls=unique(s+1,s+1+ls)-s-1; for(int i=1;i<=ls;++i) mp[s[i]]=i; Matrix tmp,ans; tmp.m=tmp.n=ls; for(int i=1;i<=m;++i) { tmp.h[mp[u[i]]][mp[v[i]]]=w[i]; tmp.h[mp[v[i]]][mp[u[i]]]=w[i]; } ans=tmp; --k; while(k>0) { if(k&1) ans=ans+tmp; tmp=tmp+tmp; k>>=1; } printf("%d\n",ans.h[mp[f]][mp[t]]); return 0; }