The main idea is to ask for the shortest path from S to T of K-steps.
Idea: Set F[P][I][J] for the shortest path from I to J just walk 2^p step, the DP equation is very simple:f[p][i][j] = min (F[p][i][j],f[p-1][i][k] + f[p-1][k][j]);
The total number of steps T binary split, in T has 1 position, if this position is P, then use f[p][][] to update the answer g[][], and finally get the g[][] is the answer matrix.
Attention to Discretization:
CODE:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 210using namespace std; #define MIN (a) < (b) (a):(B) #define MAX (a) (a) > (b)? (a):(B)) struct complex{int x,y,len; void Read () {scanf ("%d%d%d", &len,&x,&y); }}edge[max]; Pair<int,int *> Xx[1010];int cnt,t; int T,edges,points,start,end;int F[20][max][max],g[max][max],h[max][max]; int main () {cin >> T >> edges >> start >> end; memset (G,0x3f,sizeof (g)); memset (F,0x3f,sizeof (f)); for (int i = 1; I <= edges; ++i) {edge[i]. Read (); Xx[++cnt].first = Edge[i].x,xx[cnt].second = &edge[i].x; Xx[++cnt].first = Edge[i].y,xx[cnt].second = &edge[i].y; } Xx[++cnt].first = Start,xx[cnt].second = &start; Xx[++cnt].first = End,xx[cnt].second = &end; Sort (xx + 1,xx + cnt + 1); for (int i = 1; I <= cnt; ++i) {if (i = = 1 | | Xx[i].first! = xx[i -1].first) ++t; *xx[i].second = t; } for (int i = 1; I <= edges; ++i) f[0][edge[i].x][edge[i].y] = f[0][edge[i].y][edge[i].x] = min (F[0][edge[i]. X][edge[i].y],edge[i].len); points = t; for (int i = 1; I <= points; ++i) g[i][i] = 0; int p = 0; while (T) {if (t&1) {memset (h,0x3f,sizeof (h)); for (int k = 1, k <= points; ++k) for (int i = 1; I <= points; ++i) for (int j = 1; j <= points; ++J) H[i][j] = min (H[i][j],g[i][k] + f[p][k][j]); memcpy (G,h,sizeof (g)); } T >>= 1; ++p; for (int k = 1, k <= points; ++k) for (int i = 1; I <= points; ++i) for (int j = 1; J <= P oints; ++J) F[p][i][j] = min (F[p][i][j],f[p-1][i][k] + f[p-1][k][j]); } cout << G[start][end] << Endl; return 0;}
Bzoj 1706 Usaco Relays Cow relay run/POJ 3613 Cow relays multiply Floyd