POJ 3613 Cow Relays
阿新 • • 發佈:2019-02-23
長度 book 最短 floyd amp sca mat 定義 sort
題目大意:給定起點和終點,求經過k條邊的最短路
思路:倍增Floyd 矩陣快速冪優化
其實,雖然被稱作倍增Floyd,但和Floyd關系好像並不大?按dp思想理解,設f(k,i,j)表示經過k條邊從i到j的最小花費,則
\(f(k,i,j)=min(f(k-1,i,p)+f(1,p,j))\)
k次Floyd顯然會超時,現考慮定義新運算如下:
對一張有n個點的圖,用n*n的鄰接矩陣來存儲,其中(i,j)表示從i到j的最短路長度
A矩陣表示經過x條邊以後的最短路,B矩陣表示經過y條邊以後的最短路
定義新運算:\(A*B=C\)
\(C[i,j]=min_{k=1}^nA[i,k]+B[k,j]\)
對這種矩陣運算,滿足結合律,可以用類似快速冪的倍增思想進行優化
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=210;//註意空間限制 數組開大直接報錯 int s,e,k,n,m,book[3005]; struct data {//離散化用 int from,to,dis; } node[3005]; struct Matrix { int mp[maxn][maxn]; inline Matrix () {memset(mp,0x3f,sizeof(mp));} Matrix operator *(const Matrix &a)const { Matrix c; for(int k=1; k<=n; ++k) for(int i=1; i<=n; ++i) for(int j=1; j<=n; ++j) c.mp[i][j]=min(c.mp[i][j],mp[i][k]+a.mp[k][j]); return c; } } f,ans; void ksm(){ ans=f; while(k) { if(k&1) ans=ans*f; f=f*f; k>>=1; } } int main() { scanf("%d%d%d%d",&k,&m,&s,&e); for(int i=1,x,y,z; i<=m; ++i) { scanf("%d%d%d",&z,&x,&y); book[++n]=x; book[++n]=y; node[i].from=x; node[i].to=y; node[i].dis=z; } sort(book+1,book+1+n); int tot=unique(book+1,book+1+n)-(book+1); for(int i=1; i<=m; ++i) { node[i].from=lower_bound(book+1,book+1+tot,node[i].from)-book; node[i].to=lower_bound(book+1,book+1+tot,node[i].to)-book; f.mp[node[i].from][node[i].to]=f.mp[node[i].to][node[i].from]=node[i].dis; } s=lower_bound(book+1,book+1+tot,s)-book; e=lower_bound(book+1,book+1+tot,e)-book; n=tot; //以上為離散化內容 --k;//經過k條邊 需要進行k-1次floyd ksm(); printf("%d",ans.mp[s][e]); return 0; }
POJ 3613 Cow Relays