POJ3613 k邊最短路
阿新 • • 發佈:2018-04-12
turn ref 最短路 pan name UC pre memset style
題目:http://poj.org/problem?id=3613
Floyd求最短路的實質是矩陣的自乘。( i , k )是第 i 行第k列,( k , j )是第k行第 j 列;用它們的max更新( i , j ),正是矩陣的自乘。
給一個矩陣賦予“已走 r 條邊”的意義,則已走m條邊的矩陣×已走n條邊的矩陣得到的是已走m+n條邊的矩陣。
用快速冪一樣的方法加速,就行了。
重載運算符有待練習。
註意要先ans=a,n - -,原因見註釋。
#include<iostream> #include<cstdio> #include<cstring> using namespacestd; typedef long long ll; const int N=205; int n,m,s,t,map[1005],cnt; struct Jz{ ll c[N][N]; Jz operator * (const Jz &a) const { Jz tmp; memset(tmp.c,1,sizeof tmp.c); for(int k=1;k<=cnt;k++) for(int i=1;i<=cnt;i++) for(int j=1;j<=cnt;j++) tmp.c[i][j]=min(tmp.c[i][j],c[i][k]+a.c[k][j]); // printf("k=%d i=%d j=%d c=%lld\n",k,i,j,c[i][k]);// return tmp; } }ans,a; int main() { memset(a.c,1,sizeof a.c); scanf("%d%d%d%d",&n,&m,&s,&t); int x,y;ll z; for(int i=1;i<=m;i++) { scanf("%lld%d%d",&z,&x,&y); // printf("(%lld)",z); if(!map[x])map[x]=++cnt; if(!map[y])map[y]=++cnt; a.c[map[x]][map[y]]=a.c[map[y]][map[x]]=min(a.c[map[x]][map[y]],z); // printf("(%d %d %lld %lld)",map[x],map[y],a.c[map[x]][map[y]],ans.c[map[x]][map[y]]); } // printf("[%d %d %d %d]\n",map[4],map[6],map[8],map[9]); // printf("(%lld)",a.c[map[s]][map[t]]); ans=a;n--;///////不然i,j的值就改成min(k,j)了! for(;n;n>>=1) { if(n&1)ans=ans*a; a=a*a; } printf("%lld",ans.c[map[s]][map[t]]); return 0; }
POJ3613 k邊最短路