For the shortest path, the path with the smallest Lexicographic Order must be output.
Spfa: Takes a pre [] record precursor. The difference is that when we relax, we should consider the situation where the dis value is equal to the current point, the solution is that dfs finds out that the Lexicographic Order in the two paths is small and pre [] is used for updating. Treat the path as a string.
I only use the pre to update the current vertex without considering the entire path from the start point to the current vertex. In fact, this does not ensure that the Lexicographic Order is the minimum. After wa N times, I searched for the problem and found that spfa was rarely used. I felt very good when I saw a great solution.
# Include
# Include
# Include
# Include
# Include
# Include
# Include
# Define LL long # define _ LL _ int64using namespace std; const int INF = 0x3f3f3f3f; const int maxn = 110; int n; int tax [maxn]; int Map [maxn] [maxn]; int dis [maxn], inque [maxn]; int pre [maxn]; int pos = 0; void dfs (int u, char * s) {if (u =-1) return; dfs (pre [u], s); s [pos ++] = u + '0 ';} bool solve (int v, int u) {char s1 [maxn], s2 [maxn]; // find the previous path pos = 0; dfs (v, s1 ); s1 [pos] = ''; // find the path pos updated by u = 0; dfs (u, s2); s2 [pos ++] = v + '0 '; s2 [pos] = ''; if (strcmp (s1, s2)> 0) return true; return false;} int spfa (int s, int t) {queue
Que; memset (dis, INF, sizeof (dis); memset (inque, 0, sizeof (inque); memset (pre,-1, sizeof (pre )); dis [s] = 0; inque [s] = 1; que. push (s); while (! Que. empty () {int u = que. front (); que. pop (); inque [u] = 0; for (int v = 1; v <= n; v ++) {if (Map [u] [v]> 0) {int tmp = dis [u] + Map [u] [v] + tax [v]; if (tmp <dis [v]) // directly update {dis [v] = tmp; pre [v] = u; if (! Inque [v]) {inque [v] = 1; que. push (v) ;}} else if (tmp = dis [v] & solve (v, u) {pre [v] = u ;}}}} return dis [t];} void output (int s, int t) {int res [maxn]; int cnt = 0; int tmp = t; while (pre [tmp]! =-1) {res [cnt ++] = tmp; tmp = pre [tmp];} res [cnt] = s; printf (Path :); for (int I = cnt; I> = 1; I --) printf (% d -->, res [I]); printf (% d, res [0]);} int main () {while (~ Scanf (% d, & n) {for (int I = 1; I <= n; I ++) {for (int j = 1; j <= n; j ++) scanf (% d, & Map [I] [j]) ;}for (int I = 1; I <= n; I ++) scanf (% d, & tax [I]); int u, v; while (~ Scanf (% d, & u, & v) {if (u =-1 & v =-1) break; int tmp1 = tax [u]; // backup int tmp2 = tax [v]; tax [u] = 0; tax [v] = 0; printf (From % d to % d:, u, v ); int ans = spfa (u, v); output (u, v); printf (Total cost: % d, ans); // restore backup tax [u] = tmp1; tax [v] = tmp2 ;}} return 0 ;}
Floyd: pre [I] [j] records the point closest to I from the I TO THE j path, and the output path is pre-forwarded. It seems that floyd is very powerful. You can record the path in this way.
# Include
# Include
# Include
# Include
# Include
# Include
# Include
# Include
# Define LL long # define _ LL _ int64using namespace std; const int INF = 0x3f3f3f3f; const int maxn = 110; int Map [maxn] [maxn]; int tax [maxn]; int pre [maxn] [maxn]; int n; void floyd () {// initialize for (int I = 1; I <= n; I ++) for (int j = 1; j <= n; j ++) pre [I] [j] = j; for (int k = 1; k <= n; k ++) {for (int I = 1; I <= n; I ++) {for (int j = 1; j <= n; j ++) {if (Map [I] [k]> 0 & Map [k] [j]> 0) {int tmp = Map [I] [K] + Map [k] [j] + tax [k]; if (tmp <Map [I] [j]) // less than directly update {Map [I] [j] = tmp; pre [I] [j] = pre [I] [k];} else if (tmp = Map [I] [j]) {pre [I] [j] = min (pre [I] [k], pre [I] [j]) ;}}}} void output (int s, int t) {printf (Path:); int tmp = s; while (tmp! = T) {printf (% d -->, tmp); tmp = pre [tmp] [t];} printf (% d, t);} int main () {while (~ Scanf (% d, & n) {for (int I = 1; I <= n; I ++) for (int j = 1; j <= n; j ++) {scanf (% d, & Map [I] [j]); if (Map [I] [j] =-1) map [I] [j] = INF ;}for (int I = 1; I <= n; I ++) scanf (% d, & tax [I]); int u, v; floyd (); while (~ Scanf (% d, & u, & v) {if (u =-1 & v =-1) break; printf (From % d to % d:, u, v); output (u, v); printf (Total cost: % d, map [u] [v]) ;}} return 0 ;}