题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1385
题目大意:
给你一个无向图,求任意两点的最短路。附加条件2个:
1.经过每个节点必须缴纳一点的税。
2.如果有多条最短路径,寻找字典序最小的路径。
思路:
Floyd算法+path数组保存路径+字典序更新
代码如下:
#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; }