1. 程式人生 > >bzoj 1706: [usaco2007 Nov]relays 奶牛接力跑【矩陣乘法+Floyd】

bzoj 1706: [usaco2007 Nov]relays 奶牛接力跑【矩陣乘法+Floyd】

mes AD etc err 一次 鄰接矩陣 a* 是把 for

唔不知道怎麽說……大概核心是把矩陣快速冪的乘法部分變成了Floyd一樣的東西,非常之神
首先把點離散一下,最多有200個,然後建立鄰接矩陣,a[u][v]為(u,v)之間的距離,沒路就是inf
然後註意重載乘號的部分,註意到這樣乘一次就相當於把本來存了經過k條路的最短路的鄰接矩陣變成存了經過k+1條路的最短路的鄰接矩陣
這樣看來乘n次就行了,這裏用矩陣快速冪
妙啊

#include<iostream>
#include<cstdio>
using namespace std;
const int N=1005;
const long long inf=1e15;
int n,m,s,t,id[N],tot;
struct
qwe { long long a[205][205]; qwe operator * (const qwe &b) const { qwe c; for(int i=1;i<=tot;i++) for(int j=1;j<=tot;j++) c.a[i][j]=inf; for(int k=1;k<=tot;k++) for(int i=1;i<=tot;i++) for(int
j=1;j<=tot;j++) c.a[i][j]=min(c.a[i][j],a[i][k]+b.a[k][j]); return c; } }a,r; int read() { int r=0,f=1; char p=getchar(); while(p>‘9‘||p<‘0‘) { if(p==‘-‘) f=-1; p=getchar(); } while(p>=‘0‘&&p<=‘9‘
) { r=r*10+p-48; p=getchar(); } return r*f; } int main() { n=read(),m=read(),s=read(),t=read(); for(int i=1;i<=m;i++) { int z=read(),x=read(),y=read(); x=(id[x]!=0)?id[x]:(id[x]=++tot); y=(id[y]!=0)?id[y]:(id[y]=++tot);//cerr<<x<<" "<<y<<endl; a.a[x][y]=a.a[y][x]=z; } for(int i=1;i<=tot;i++) for(int j=1;j<=tot;j++) if(!a.a[i][j]) a.a[i][j]=inf; int x=n-1; r=a; while(x) { if(x&1) r=r*a; a=a*a; x>>=1; } printf("%lld\n",r.a[id[s]][id[t]]); return 0; }

bzoj 1706: [usaco2007 Nov]relays 奶牛接力跑【矩陣乘法+Floyd】