[bzoj1706] [usaco2007 Nov]relays 奶牛接力跑
大概是叫倍增Floyd?
显然最多200个点...f[i][j][k]表示从j到k,走2^i步的最小路程。就随便转移了。。
查询的话就是把n二进制位上是1的那些都并起来。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<cstdlib> 6 #define ll long long 7 #define ull unsigned long long 8 #define d double 9 using namespace std; 10 const int maxn=1023,inf=1002333333; 11 struct mat{int f[202][202];}f,c; 12 int id[1023]; 13 int i,j,k,n,m,cnt,st,ed; 14 15 int ra,fh;char rx; 16 inline int read(){ 17 rx=getchar(),ra=0,fh=1; 18 while((rx<'0'||rx>'9')&&rx!='-')rx=getchar(); 19 if(rx=='-')fh=-1,rx=getchar(); 20 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh; 21 } 22 inline int min(int a,int b){return a<b?a:b;} 23 inline mat run(mat &a,mat &b){ 24 register int i,j,k; 25 for(i=1;i<=cnt;i++)for(j=1;j<=cnt;j++) 26 for(c.f[i][j]=inf,k=1;k<=cnt;k++) 27 c.f[i][j]=min(c.f[i][j],a.f[i][k]+b.f[k][j]); 28 return c; 29 } 30 int main(){ 31 n=read(),m=read(),st=read(),ed=read();int x; 32 memset(f.f,60,sizeof(f.f)); 33 for(i=1;i<=m;i++){ 34 x=read(),j=read(),k=read(); 35 if(!id[j])id[j]=++cnt;if(!id[k])id[k]=++cnt; 36 j=id[j],k=id[k]; 37 f.f[j][k]=min(f.f[j][k],x),f.f[k][j]=min(f.f[k][j],x); 38 } 39 mat g=f;n--; 40 while(n){ 41 if(n&1)g=run(g,f); 42 n>>=1; 43 if(n)f=run(f,f); 44 } 45 printf("%d\n",g.f[id[st]][id[ed]]); 46 }