这篇博文重点讲状态依赖的最短路问题 
以spfa,负环判断为主 
另外还讲了一些最短路算法在实践中的应用
 
状态依赖的SPFA算法 
电梯调度问题 
( x , j ) (x, j) ( x , j )   表示电梯当前在 x x x   层,手柄位置为 j j j  
spfa queue statues \text{spfa queue statues} spfa queue statues : = v i s ( x , j ) := vis(x, j) : = v i s ( x , j ) 
for   ∀ i ∈ [ 1 , m ] ↔ next position \textbf{for}\  \forall i \in [1, m] \leftrightarrow \text{next position} for   ∀ i ∈ [ 1 , m ] ↔ next position  
       ~~~~~~             w = ∣ i − j ∣ + 2 ∣ C ( i ) ∣ w=|i-j|+2|C(i)| w = ∣ i − j ∣ + 2 ∣ C ( i ) ∣ 
d ( x + C [ i ] , i ) = min  { d ( x + C [ i ] , i ) , d ( x , j ) + w }   run spfa() \begin{gathered}
d(x+C[i], i) = \min\{d(x+C[i],i), d(x,j)+w\} \\ \ \\
\text{run spfa()}
\end{gathered}
 d ( x + C [ i ] , i ) = min { d ( x + C [ i ] , i ) , d ( x , j ) + w }   run spfa()  
spfa算法注意点  
在计算下一个状态的时候  
判断 
 
1 2 3 4 5 6 if (D[next] > D[cur] + w) {    if (!inq[next]) {         que.push(next);         inq[next] = 1;      } } 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 const int maxn = 1000 + 5; const int maxm = 20 + 5; const int inf = 0x3f3f3f3f; int n, m; int D[maxn][maxm], inq[maxn][maxm]; typedef pair<int, int> PII; int C[maxn]; // == run spfa == void initSpfa  () {     Set(inq, 0);     Set(D, inf); } void spfa(int st_x, int st_j) {     queue<PII> que;     que.push(MPR(st_x, st_j));     D[st_x][st_j] = 0;     inq[st_x][st_j] = 1;     while  (!que.empty()) {         int x = que.front().first;         int j = que.front().second;         que.pop();         inq[x][j] = 0;         _rep(i, 1, m) {             int nx = x + C[i];             int w = abs(i - j) + 2 * abs(C[i]);             if (nx < 1 || nx > n) continue ;             if (D[nx][i] > D[x][j] + w) {                 D[nx][i] = D[x][j] + w;                 if (!inq[nx][i]) {                     que.push(MPR(nx, i));                     inq[nx][i] = 1;                 }             }         }     } } // == spfa finsihed == int main  () {     freopen("input.txt" , "r" , stdin);     scanf("%d%d" , &n, &m);     int pos = 0;     _rep(i, 1, m) {         scanf("%d" , &C[i]);         if (C[i] == 0) pos = i;     }     // then  spfa     initSpfa();     spfa(1, pos);     int ans = inf;     _rep(i, 1, m) ans = min(ans, D[n][i]);     if (ans == inf) puts("-1" );     else  printf ("%d\n" , ans); } 
 
floyd路径统计 
algorithm 
c ( i , j ) c(i, j) c ( i , j )   用来记录 i → j i \rightarrow j i → j   最短路的条数
for   ∀ e ( u , v ) ∈ E ( G ) \textbf{for} \  \forall e(u, v) \in E(G) for   ∀ e ( u , v ) ∈ E ( G )  
       ~~~~~~             init :   c ( u , v ) = 1 \text{init}: \ c(u, v) = 1 init :   c ( u , v ) = 1 
 
if d ( u , v ) > d ( u , k ) + d ( k , v ) \textbf{if} \quad  d(u,v) > d(u, k) + d(k, v) if d ( u , v ) > d ( u , k ) + d ( k , v )  
       ~~~~~~             c ( u , v ) = c ( u , k ) ⋅ c ( k , v ) c(u, v) = c(u, k) \cdot c(k, v) c ( u , v ) = c ( u , k ) ⋅ c ( k , v ) 
if d ( u , v ) = d ( u , k ) + d ( k , v ) \textbf{if} \quad d(u, v) = d(u, k) + d(k, v) if d ( u , v ) = d ( u , k ) + d ( k , v )  
       ~~~~~~             c ( u , v ) + = c ( u , k ) ⋅ c ( k , v ) c(u, v) += c(u, k) \cdot c(k, v) c ( u , v ) + = c ( u , k ) ⋅ c ( k , v ) 
 
经过 k k k   的最短路,满足 floyd \textbf{floyd} floyd   方程 
∀ ( i , j ) , i ≠ j , d ( i , j ) = d ( i , k ) + d ( k , j ) \forall (i, j), i \neq j, \quad d(i,j) = d(i,k)+d(k, j) ∀ ( i , j ) , i  = j , d ( i , j ) = d ( i , k ) + d ( k , j ) 
 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 const int maxn = 100 + 10; const int inf = 0x3f3f3f3f; int n, m; int d[maxn][maxn]; ll c[maxn][maxn]; double ans[maxn]; void initFloyd  () {     Set(d, inf);     _rep(i, 0, n) d[i][i] = 0;     Set(c, 0);     Set(ans, 0.0); } void floyd  () {     _rep(k, 1, n) _rep(i, 1, n) _rep(j, 1, n) {         if (i != j && k != i && k != j) {             if (d[i][j] > d[i][k] + d[k][j]) {                 d[i][j] = d[i][k] + d[k][j];                 c[i][j] = 1ll * c[i][k] * c[k][j];             }             else  if (d[i][j] == d[i][k] + d[k][j]) {                 c[i][j] += 1ll * c[i][k] * c[k][j];             }         }     } } void solve  () {     _rep(k, 1, n) _rep(i, 1, n) _rep(j, 1, n) {         if (i != j && k != i && k != j) {             if (d[i][j] == d[i][k] + d[k][j]) {                 ans[k] += (double) c[i][k] * c[k][j] / c[i][j];             }         }     }     _rep(i, 1, n) printf ("%.3lf\n" , ans[i]); } int main  () {     freopen("input.txt" , "r" , stdin);     scanf("%d%d" , &n, &m);     initFloyd();     _for(i, 0, m) {         int x, y, z;         scanf("%d%d%d" , &x, &y, &z);         d[x][y] = d[y][x] = z;         c[x][y] = c[y][x] = 1ll;     }     floyd();     solve(); } 
 
Dijkstra和DAG上的dp 
algorithm \textbf{algorithm} algorithm 
run dijkstra() \text{run dijkstra()} run dijkstra()  
       ~~~~~~             we   get   ∀ u ,   D(u) \textbf{we}\  \textbf{get} \ \forall u, \ \textbf{D(u)} we   get   ∀ u ,   D(u)  
dp ( s t ← e d ) ,   begin:   consider   ed \textbf{dp}(st\leftarrow ed) ,\ \textbf{begin:} \ \textbf{consider} \  \textbf{ed} dp ( s t ← e d ) ,   begin:   consider   ed  
       ~~~~~~             f ( e d ) = 1 , f ( v / e d ) = 0 f(ed) = 1, f(v/ed) = 0 f ( e d ) = 1 , f ( v / e d ) = 0  
       ~~~~~~             sort   according   to   D [ u ] → o r d [ ⋯   ] ,   o r d 0 = e d \textbf{sort} \ \textbf{according} \ \textbf{to} \  D[u]\rightarrow ord[\cdots], \ ord_0 = ed sort   according   to   D [ u ] → o r d [ ⋯ ] ,   o r d 0  = e d  
       ~~~~~~             now   D ( o r d 0 ) = 0 , D ( o r d 1 ) , D ( o r d 2 ) ↑ ⋯ \textbf{now} \ D(ord_0)=0, D(ord_1), D(ord_2) \uparrow \cdots now   D ( o r d 0  ) = 0 , D ( o r d 1  ) , D ( o r d 2  ) ↑ ⋯  
       ~~~~~~             for   ∀ x = o r d i   for   ∀ e ( x , y ) \textbf{for} \ \forall x = ord_i \  \textbf{for} \ \forall e(x, y) for   ∀ x = o r d i    for   ∀ e ( x , y )  
       ~~~~~~                  ~~~~         if   D ( y ) > D ( x ) , f ( y ) + = f ( x ) \textbf{if} \ D(y) > D(x), f(y) += f(x) if   D ( y ) > D ( x ) , f ( y ) + = f ( x )  
       ~~~~~~             ans is  f ( s t ) \text{ans is } f(st) ans is  f ( s t )  
 
in this case, run dp() in  every   node \text{in this case, run dp() in } \textbf{every} \ \textbf{node} in this case, run dp() in  every   node 
dp ( s t → e d ) , begin:   consider   dp(st,   ed) \textbf{dp}(st\rightarrow ed), \textbf{begin:} \ \textbf{consider} \  \textbf{dp(st,} \ \textbf{ed)} dp ( s t → e d ) , begin:   consider   dp(st,   ed)  
       ~~~~~~             init   set   f [ ⋯   ] ← − 1 \textbf{init} \ \textbf{set} \ f[\cdots] \leftarrow -1 init   set   f [ ⋯ ] ← − 1  
       ~~~~~~             dp ( x , e d ) \textbf{dp}(x, ed) dp ( x , e d )  
       ~~~~~~                  ~~~~         if   x = e d , return  1 \textbf{if} \ x = ed, \text{return } 1 if   x = e d , return  1  
       ~~~~~~                  ~~~~         if   f ( x ) ⩾ 0 , found ans, return  f ( x ) \textbf{if} \ f(x) \geqslant 0, \text{found ans, return } f(x) if   f ( x ) ⩾ 0 , found ans, return  f ( x )  
       ~~~~~~                  ~~~~         let   f ( x ) = 0 , for   ∀ e ( x , y ) \textbf{let} \ f(x) = 0, \textbf{for} \ \forall e(x, y) let   f ( x ) = 0 , for   ∀ e ( x , y )  
       ~~~~~~                  ~~~~              ~~~~         if   D ( y ) < D ( x ) , f ( x ) + = d p ( y , e d ) \textbf{if} \ D(y) < D(x), f(x) +=dp(y, ed) if   D ( y ) < D ( x ) , f ( x ) + = d p ( y , e d )  
       ~~~~~~                  ~~~~         return  f ( x ) \text{return } f(x) return  f ( x )  
 
run dp() recursive  \text{run dp() recursive } run dp() recursive  
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 const int maxn = 1000 + 10; const int inf = 0x3f3f3f3f; int n, m; // == Graph definition == vector<int> G[maxn]; class Edge { public:     int to, weight;     Edge  () {}     Edge(int t, int w) : to(t), weight(w) {} }; vector<Edge> edges; void initG  () {     _for(i, 0, maxn) G[i].clear();     edges.clear(); } void addEdge(int u, int v, int w) {     edges.push_back(Edge(v, w));     G[u].push_back(edges.size() - 1); } class Node { public:     int u, dist;     bool operator< (const Node& rhs) const {         return  dist > rhs.dist;     }     Node  () {}     Node(int u, int d) : u(u), dist(d) {} }; // == Graph finished == // == dijkstra == int D[maxn], vis[maxn]; void initDij(int st) {     Set(D, inf);     D[st] = 0;     Set(vis, 0); } void dijkstra(int st) {     initDij(st);     priority_queue<Node> que;     que.push(Node(st, 0));     while  (!que.empty()) {         int x = que.top().u;         que.pop();         if (vis[x]) continue ;         vis[x] = 1;         _for(i, 0, G[x].size()) {             const Edge& e = edges[G[x][i]];             int y = e.to;             if (D[y] > D[x] + e.weight) {                 D[y] = D[x] + e.weight;                 que.push(Node(y, D[y]));             }         }     } } // == dijkstra finished == // == dp == inline bool cmp(int a, int b) {     return  D[a] < D[b]; } int ord[maxn]; int f[maxn]; void initDP(const int ed) {     _rep(i, 1, n) ord[i] = i;     sort(ord + 1, ord + 1 + n, cmp);     //assert(ed == ord[1]);     Set(f, 0);     f[ed] = 1; } void dp(const int st) {     _rep(i, 1, n) {         int x = ord[i];         _for(j, 0, G[x].size()) {             int y = edges[G[x][j]].to;             if (D[y] > D[x]) f[y] += f[x];         }     }     printf ("%d\n" , f[st]); } void initDP  () {     Set(f, -1); } int dp(int x, const int ed) {     if (x == ed) return  1;     if (f[x] >= 0) return  f[x];     f[x] = 0;     _for(i, 0, G[x].size()) {         int y = edges[G[x][i]].to;         if (D[y] < D[x]) f[x] += dp(y, ed);     }     return  f[x]; } // == dp finsiehd == int main  () {     freopen("input.txt" , "r" , stdin);     while  (scanf("%d%d" , &n, &m) == 2 && n) {         initG();         _for(i, 0, m) {             int x, y, z;             scanf("%d%d%d" , &x, &y, &z);             addEdge(x, y, z);             addEdge(y, x, z);         }         // run dijkstra         dijkstra(2);         // then  dp         initDP(2);         dp(1);         //initDP();         //printf ("%d\n" , dp(1, 2));     } } 
 
最短路树 
algorithm:   e ( x , u ) : = p ( u )   is   the   forward   arc(前向弧) \textbf{algorithm:} \ e(x, u):=p(u) \ \textbf{is} \  \textbf{the} \ \textbf{forward} \ \textbf{arc(前向弧)} algorithm:   e ( x , u ) : = p ( u )   is   the   forward   arc( 前向弧 )  
run   d i j k s t r a ( )  and record  p ( ) \textbf{run} \ dijkstra() \text{ and record } p() run   d i j k s t r a ( )  and record  p ( ) 
Dijkstra-Tree   := ⋃ p ( u ) ∈ p a t h e ( p ( u ) ) \textbf{Dijkstra-Tree} \ \textbf{:=} \bigcup\limits_{p(u) \in path}e(p(u))
 Dijkstra-Tree   := p ( u ) ∈ p a t h ⋃  e ( p ( u ) ) 
init: W ( u , v ) = ⋃ w e i g h t s w ( u , v ) \textbf{init:} \quad W(u, v) = \bigcup\limits_{weights}w(u, v) init: W ( u , v ) = w e i g h t s ⋃  w ( u , v )  
multiple edges,  i d x ( u , v ) : = edge number \text{multiple edges, } idx(u, v) := \text{edge number} multiple edges,  i d x ( u , v ) : = edge number  
u s e d ( s r c , u , v ) : =  run dijkstra ( s r c ) , e ( u , v )  is Tree-edge or not used(src, u, v):= \text{ run dijkstra}(src), e(u, v)\text{ is Tree-edge or not} u s e d ( s r c , u , v ) : =  run dijkstra ( s r c ) , e ( u , v )  is Tree-edge or not 
 
for   ∀ s r c ∈ V ( G ) \textbf{for} \  \forall src \in V(G) for   ∀ s r c ∈ V ( G )  
       ~~~~~~             run   Dijkstra ( s r c ) →  mark  p ( ⋯   ) \textbf{run}\  \textbf{Dijkstra}(src) \rightarrow \text{ mark } p(\cdots) run   Dijkstra ( s r c ) →  mark  p ( ⋯ )  
       ~~~~~~             for   ∀ u ∈ V ( G ) , ∀ e ( u , v ) ∈ Dijkstra-Tree ( G ) \textbf{for}\  \forall u \in V(G), \forall e(u, v) \in \textbf{Dijkstra-Tree}(G) for   ∀ u ∈ V ( G ) , ∀ e ( u , v ) ∈ Dijkstra-Tree ( G )  
       ~~~~~~                  ~~~~         C ( s r c ) = ∑ u D ( u ) ,  mark  u s e d ( s r c , u , v ) C(src) = \sum_u D(u), \text{ mark } used(src, u, v) C ( s r c ) = ∑ u  D ( u ) ,  mark  u s e d ( s r c , u , v )  
ans = ∑ C ( s r c ) \textbf{ans} = \sum C(src) ans = ∑ C ( s r c ) 
 
consider   delete   operation \textbf{consider} \ \textbf{delete} \ \textbf{operation} consider   delete   operation  
       ~~~~~~             del ( u , v ) ⇒ w ( u , v ) = 0   or   w ( u , v ) = W ( u , v ) [ 2 , 3 , ⋯   ] \textbf{del}(u, v)\Rightarrow w(u, v) = 0 \ \textbf{or} \ w(u, v) = W(u, v)[2, 3, \cdots] del ( u , v ) ⇒ w ( u , v ) = 0   or   w ( u , v ) = W ( u , v ) [ 2 , 3 , ⋯ ]  
       ~~~~~~             for   ∀ s r c ∈ V ( G ) \textbf{for} \ \forall src \in V(G) for   ∀ s r c ∈ V ( G )  
           ~~~~~~~~~~                     if   u s e d ( s r c , u , v ) = 0 ,   ans   = ∑ C ( s r c ) \textbf{if} \ used(src, u, v)=0, \ \textbf{ans} \ = \sum C(src) if   u s e d ( s r c , u , v ) = 0 ,   ans   = ∑ C ( s r c )  
           ~~~~~~~~~~                     else  rebuild Dijkstra-Tree \textbf{else} \ \text{rebuild Dijkstra-Tree} else   rebuild Dijkstra-Tree  
               ~~~~~~~~~~~~~~                             run Dijkstra ( s r c ) \text{run Dijkstra}(src) run Dijkstra ( s r c )  
               ~~~~~~~~~~~~~~                             for   ∀ u ∈ V ( G ) \textbf{for} \ \forall u \in V(G) for   ∀ u ∈ V ( G )  
                   ~~~~~~~~~~~~~~~~~~                                     ans = ∑ D ( u ) \textbf{ans} = \sum D(u) ans = ∑ D ( u ) 
reset   w ( u , v ) = W ( u , v ) [ 0 ] \textbf{reset} \ w(u, v) = W(u, v)[0] reset   w ( u , v ) = W ( u , v ) [ 0 ] 
 
 
UVA1416 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 const int maxn = 100 + 10; const int inf = 0x3f3f3f3f; int n, m, L; vector<int> W[maxn][maxn]; int used[maxn][maxn][maxn]; int idx[maxn][maxn]; // == Graph definition == vector<int> G[maxn]; class Edge { public:     int from, to, weight;     Edge  () {}     Edge(int f, int t, int w) : from(f), to(t), weight(w) {} }; class Node { public:     int u, dist;     Node  () {}     Node(int u, int d) : u(u), dist(d) {}     bool operator< (const Node& rhs) const {         return  dist > rhs.dist;     } }; vector<Edge> edges; void initG  () {     _for(i, 0, maxn) G[i].clear();     edges.clear(); } void addEdge(int u, int v, int w) {     edges.push_back(Edge(u, v, w));     G[u].push_back(edges.size() - 1);     idx[u][v] = edges.size() - 1; } // == Graph finished == // == Dijkstra == int p[maxn]; int D[maxn], vis[maxn]; void initDij(int st) {     Set(p, 0);     Set(vis, 0);     Set(D, inf);     D[st] = 0; } void dijkstra(int st) {     initDij(st);     priority_queue<Node> que;     que.push(Node(st, 0));     while  (!que.empty()) {         int x = que.top().u;         que.pop();         if (vis[x]) continue ;         vis[x] = 1;         _for(i, 0, G[x].size()) {             const Edge& e = edges[G[x][i]];             int y = e.to;             if (e.weight > 0 && D[y] > D[x] + e.weight) {                 D[y] = D[x] + e.weight;                 p[y] = G[x][i];                 que.push(Node(y, D[y]));             }         }     } } // == Dijkstra finished == // == solver == int C[maxn]; void initCal  () {     Set(C, 0); } int cal  () {     initCal();     int ans = 0;     _rep(st, 1, n) {         dijkstra(st);         _rep(v, 1, n) {             if (v != st) {                 int u = edges[p[v]].from;                 used[st][u][v] = used[st][v][u] = 1;             }             C[st] += (D[v] == inf ? L : D[v]);         }         ans += C[st];     }     return  ans; } int del(int u, int v) {     Edge& e1 = edges[idx[u][v]];     Edge& e2 = edges[idx[v][u]];;     if (W[u][v].size() == 1) e1.weight = e2.weight = 0;     else  if (W[u][v].size() > 1) e1.weight = e2.weight = W[u][v][1];     int ans = 0;     _rep(st, 1, n) {         if (used[st][u][v] == 0) ans += C[st];         else  {             dijkstra(st);             _rep(i, 1, n) ans += (D[i] == inf ? L : D[i]);         }     }     e1.weight = e2.weight = W[u][v][0];     return  ans; } // == solver finsihed == void init  () {     _for(i, 0, maxn) _for(j, 0, maxn) W[i][j].clear();     Set(used, 0);     Set(idx, 0); } int main  () {     freopen("input.txt" , "r" , stdin);     while  (scanf("%d%d%d" , &n, &m, &L) == 3) {         init();         initG();         // build graph         _for(i, 0, m) {             int u, v, s;             scanf("%d%d%d" , &u, &v, &s);             W[u][v].push_back(s);             W[v][u].push_back(s);         }         _rep(i, 1, n) _rep(j, i + 1, n) {             if (W[i][j].size()) {                 sort(W[i][j].begin(), W[i][j].end());                 addEdge(i, j, W[i][j][0]);                 addEdge(j, i, W[i][j][0]);             }         }         // build finished         // solve the problem         int c1 = cal();         int c2 = -1;         _rep(i, 1, n) _rep(j, i + 1, n) if (W[i][j].size()) {             c2 = max(c2, del(i, j));         }         printf ("%d %d\n" , c1, c2);     } } 
 
Dijkstra杂题,路径输出 
ceil ( x ) : = ⩾ x (离x最近的整数) \textbf{ceil}(x) := \geqslant x \textbf{(离x最近的整数)} ceil ( x ) : = ⩾ x ( 离 x 最近的整数 )  
常常用来处理以下问题,比如每 k k k   个单位要缴纳 1 1 1   单位 
不足 1 1 1   单位按 1 1 1   单位来算
D ( u ) → x = D ( u ) + x K D ( u ) + x D(u) \xrightarrow{x=\frac{D(u)+x}{K}} D(u)+x
 D ( u ) x = K D ( u ) + x   D ( u ) + x 
( K − 1 ) x = D ( u ) ⇔ x = D ( u ) K − 1   rhs = D ( u ) + x = ceil ( D ( u ) K − 1 ⋅ K ) \begin{gathered}
(K-1)x = D(u) \Leftrightarrow x = \frac{D(u)}{K-1} \\ \ \\
\text{rhs} = D(u) + x = \textbf{ceil}(\frac{D(u)}{K-1} \cdot K)
\end{gathered}
 ( K − 1 ) x = D ( u ) ⇔ x = K − 1 D ( u )    rhs = D ( u ) + x = ceil ( K − 1 D ( u )  ⋅ K )  
run dijkstra ( ) ,   get   D t o \text{run dijkstra}(), \ \textbf{get} \ D_{to} run dijkstra ( ) ,   get   D t o   
for   ∀ e ( x , y ) \textbf{for} \ \forall e(x, y) for   ∀ e ( x , y )  
       ~~~~~~             if   D ( y ) > D t o , D ( y ) = D t o , p ( y ) = e ( x , y ) \textbf{if} \ D(y) > D_{to}, D(y)=D_{to}, p(y) = e(x, y) if   D ( y ) > D t o  , D ( y ) = D t o  , p ( y ) = e ( x , y )  
       ~~~~~~             if   D ( y ) = D t o ,   ( [ x 1 , x 2 ] , y ) ,   x 2 < x 1 \textbf{if} \ D(y) = D_{to}, \ ([x_1, x_2], y), \ x_2 < x_1 if   D ( y ) = D t o  ,   ( [ x 1  , x 2  ] , y ) ,   x 2  < x 1   
           ~~~~~~~~~~                     ( x 1 , y ) → ( x 2 , y ) , p ( y ) = e ( x 2 , y ) (x_1, y) \rightarrow (x_2, y), \quad p(y) = e(x_2, y) ( x 1  , y ) → ( x 2  , y ) , p ( y ) = e ( x 2  , y ) 
 
output path \text{output path} output path  
       ~~~~~~             run dijkstra ( e d → s t ) \text{run dijkstra}(ed\rightarrow st) run dijkstra ( e d → s t )  
       ~~~~~~             out ( e d ← s t ) \text{out}(ed \leftarrow st) out ( e d ← s t )  
       ~~~~~~             out ( u , V ( p ( u ) ) , V ( p ( p ( u ) ) ) , ⋯   ) \text{out}(u, V(p(u)), V(p(p(u))), \cdots) out ( u , V ( p ( u ) ) , V ( p ( p ( u ) ) ) , ⋯ ) 
 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 const int maxn = 100 + 5; const ll inf = 0x3f3f3f3f3f3f3f3f; int n, P, st, ed; // == Graph definition == vector<int> G[maxn]; class Edge { public:     int from, to, isUp;     Edge  () {}     Edge(int f, int t, int w) : from(f), to(t), isUp(w) {} }; vector<Edge> edges; class Node { public:     int u;     ll dist;     Node  () {}     Node(int u, ll d) : u(u), dist(d) {}     bool operator< (const Node& rhs) const {         return  dist > rhs.dist;     } }; void initG  () {     edges.clear();     _for(i, 0, maxn) G[i].clear(); } void addEdge(int u, int v, int isUp) {     edges.push_back(Edge(u, v, isUp));     G[u].push_back(edges.size() - 1); } // == Graph finsihed == inline int read  () {     char ch[9];     scanf("%s" , ch);     if (isupper(ch[0])) return  ch[0] - 'A' ;     else  return  ch[0] - 'a'  + 26; } inline char format(int u) {     return  u < 26 ? 'A'  + u : 'a'  + (u - 26); } inline bool isUp(int u) {     return  u < 26 ? 1 : 0; } // == dijkstra == ll D[maxn]; int vis[maxn]; int pid[maxn]; void initDij(ll P, int st) {     _for(i, 0, maxn) D[i] = inf;     D[st] = P;     Set(vis, 0);     Set(pid, 0);     pid[st] = -1; } void dijkstra(ll P, int st) {     initDij(P, st);     priority_queue<Node> que;     que.push(Node(st, P));     while  (!que.empty()) {         int x = que.top().u;         que.pop();         //debug(D[x]);         if (vis[x]) continue ;         vis[x] = 1;         _for(i, 0, G[x].size()) {             const Edge& e = edges[G[x][i]];             int y = e.to;             ll d_to;             if (e.isUp) d_to = (ll)ceil(D[x] * 1.0 / 19 * 20);             else  d_to = D[x] + 1;             //debug(d_to);             if (D[y] > d_to || (D[y] == d_to && format(x) < format(edges[pid[y]].from))) {                 D[y] = d_to;                 pid[y] = G[x][i];                 que.push(Node(y, D[y]));             }         }     } } void print (int u) {     if (pid[u] == -1) {         printf ("%c\n" , format(u));         return ;     }     printf ("%c-" , format(u));     print (edges[pid[u]].from); } // == dijkstra finsihed == int main  () {     freopen("input.txt" , "r" , stdin);     int kase = 0;     while  (scanf("%d" , &n) == 1 && n >= 0) {         initG();         printf ("Case %d:\n" , ++kase);         // build graph         _for(i, 0, n) {             int u = read ();             int v = read ();             if (u != v) {                 addEdge(u, v, isUp(u));                 addEdge(v, u, isUp(v));             }         }         // graph finished         // then  dijkstra         scanf("%d" , &P);         st = read ();         ed = read ();         //debug(ed);         dijkstra(P, ed);         printf ("%lld\n" , D[st]);         print (st);     } }