首先,这道题考的的内容有三点:最短路+路径标记+字典序输出
最短路这里用Floyd直接就搞出来了,二路径标记和字典序只要少做一下处理便好
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 5245 Accepted Submission(s): 1316
5 0 3 22 -1 4 3 0 5 -1 -1 22 5 0 9 20 -1 -1 9 0 4 4 -1 20 4 0 5 17 8 3 1 1 3 3 5 2 4 -1 -1 0
From 1 to 3 : Path: 1-->5-->4-->3 Total cost : 21 From 3 to 5 : Path: 3-->4-->5 Total cost : 16 From 2 to 4 : Path: 2-->1-->5-->4 Total cost : 17
#include<iostream> #include<string> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; #define N 1010 #define MAX 0x3f3f3f3f int v, dis[N][N], tax[N], path[N][N]; void Floyd() { for(int i = 1; i <= v; ++i) for(int j = 1; j <= v; ++j) path[i][j] = j; //i从j点可到达j for(int k = 1; k <= v; ++k) //Floyd算法 for(int i = 1; i <= v; ++i) for(int j = 1; j <= v; ++j) { int temp = dis[i][k] + dis[k][j] + tax[k]; if(temp < dis[i][j]) //松弛,更新最短路 { dis[i][j] = temp; path[i][j] = path[i][k]; //i经k到达j比i经j到达j短 } else if(temp == dis[i][j] && path[i][j] > path[i][k]) //寻找字典序更小的路径 path[i][j] = path[i][k]; } } int main() { int start, end; while(scanf("%d", &v) != EOF && v) { for(int i = 1; i <= v; ++i) for(int j = 1; j <= v; ++j) { scanf("%d", &dis[i][j]); dis[i][j] = (dis[i][j] == -1 ? MAX : dis[i][j]); //-1无路赋值极大 } for(int i = 1; i <= v; ++i) //税 scanf("%d", &tax[i]); Floyd(); while(scanf("%d%d", &start, &end) != EOF && start != -1 && end != -1) { printf("From %d to %d :\n", start, end); printf("Path: %d", start); int res = start; while(res != end) //最短路径 { printf("-->%d", path[res][end]); res = path[res][end]; } printf("\nTotal cost : %d\n\n", dis[start][end]); //最短路权值 } } return 0; }