题目链接:
https://vjudge.net/problem/ZOJ-1456
题目大意:
Spring国家有N个城市,每队城市之间也许有运输路线,也可能没有。现在有一些货物要从一个城市运到另一个城市。运输费有两部分组成:
城市之间的运输成本,路过一个城市的税,除了起点和终点城市。多条路要求字典序最小
思路:
此处运用Floyd的思想,由于每经过一个城市需要交纳费用,所以在加入城市k的时候判断d[i][j]和d[i][k]+d[k][j]+w[k]的大小,此处需要防止i和j等于k的情况。字典序最小存路径就不能按照原来的方法倒叙存储路径,此处的path[i][j]存储的是点i到达点j的最短路径上点i后面的点。初始化的时候如果点a和点b之间存在路径,那么path[a][b] = b,每次加入中间点k时,如果可以更新最短路,path[i][j]应该等于path[i][k],因为存的是i到j的最短路径上i点后面的那个点的值,如果k点加入可以更新最短路,那么从i到j的路径上i点后面的点应该变成从i到k的路径上i点后面的点的值。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 #include<stack> 8 #include<map> 9 #include<set> 10 #include<sstream> 11 using namespace std; 12 typedef long long ll; 13 const int maxn = 1e2 + 10; 14 const int INF = 1e9 + 7; 15 int T, n, m, cases; 16 int Map[maxn][maxn]; 17 int path[maxn][maxn];//path[i][j]存从i点出发到j带你的路径上,i点的后一个点 18 int w[maxn]; 19 int main() 20 { 21 while(cin >> n && n) 22 { 23 memset(path, -1, sizeof(path)); 24 for(int i = 1; i <= n; i++) 25 { 26 for(int j = 1; j <= n; j++) 27 { 28 cin >> Map[i][j]; 29 if(Map[i][j] < 0)Map[i][j] = INF; 30 else if(i != j)path[i][j] = j; 31 } 32 } 33 for(int i = 1; i <= n; i++) 34 { 35 cin >> w[i]; 36 } 37 for(int k = 1; k <= n; k++) 38 { 39 for(int i = 1; i <= n; i++) 40 { 41 for(int j = 1; j <= n; j++) 42 { 43 if(i == k || j == k)continue; 44 if(Map[i][j] > Map[i][k] + w[k] + Map[k][j]) 45 { 46 Map[i][j] = Map[i][k] + Map[k][j] + w[k]; 47 path[i][j] = path[i][k]; 48 } 49 else if(Map[i][j] == Map[i][k] + Map[k][j] + w[k] && path[i][j] != -1 && path[i][k] != -1) 50 { 51 path[i][j] = min(path[i][j], path[i][k]); 52 } 53 } 54 } 55 } 56 int u, v; 57 while(cin >> u >> v && (u + v > 0)) 58 { 59 printf("From %d to %d : ", u, v); 60 int x = u; 61 printf("Path: %d", x); 62 while(x != v) 63 { 64 printf("-->%d", path[x][v]); 65 x = path[x][v]; 66 } 67 puts(""); 68 printf("Total cost : %d ", Map[u][v]); 69 } 70 } 71 return 0; 72 }