1. 程式人生 > >POJ3613 k邊最短路

POJ3613 k邊最短路

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 namespace
std; 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邊最短路