PAT 1111 —— Online Map(Dijkstra单源最短路径)
2018-03-14 13:57
435 查看
题目注意事项:
[b]迪杰斯特拉两次:[/b]第一次求最短的路程长度【顺便记录时间用时,以判断长度相同的时候选择时间短的】
第二次求最短的路程时间【顺便记录到达每个点的最短路径所需要的点数,以判断时间相同时候选择点数少的】【注意:第一次求得时间记录需要重新初始化以免错误】
[b]直接通过 vector < int > 判断最终两条路径是否重合[/b]
#include <cstdio> #include <vector> #include <iostream> #include <algorithm> using namespace std; bool pathIsSame(const vector<int> &a, const vector<int> &b) { unsigned i = 0; for (; i < a.size() && i < b.size(); ++i) { if(a[i] != b [i]) { return false; } } return i == a.size() && i == b.size(); } int streetLength[501][501]; int streetTime[501][501]; int main() { int N, M;//城市与街道 scanf_s("%d%d", &N, &M); for (int i = 0; i < 501; ++i) { for(int j = 0; j < 501; ++j) { if(i == j) { streetLength[i][j] = 0; streetTime[i][j] = 0; }else { streetLength[i][j] = 99999999; streetTime[i][j] = 99999999; } } } for(int i = 0; i < M; ++i) { int v1, v2, oneWay, length, time; scanf_s("%d%d%d%d%d", &v1, &v2, &oneWay, &length, &time); streetLength[v1][v2] = length; streetTime[v1][v2] = time; if(oneWay != 1) { streetLength[v2][v1] = length; streetTime[v2][v1] = time; } } int sourceV1, destinationV2;//源点和目的地 scanf_s("%d%d", &sourceV1, &destinationV2); //--保存每个点的最短路径的前驱节点号 int lengthPos[501], timePos[501]; //--保存source源点到其他点的最短路径和时间 int lengthDis[501], timeDis[501]; for (int i = 0; i < N; ++i) { if(i != sourceV1)//先确定不是源点 { lengthDis[i] = streetLength[sourceV1][i]; timeDis[i] = streetTime[sourceV1][i]; } lengthPos[i] = -1; timePos[i] = -1; } //--S集合保存哪些点是已经确定的最短路径点 int LengthS[501], TimeS[501]; for (int i = 0; i < N; ++i) { LengthS[i] = 0; TimeS[i] = 0; } //--Dijkstra核心算法(松弛) LengthS[sourceV1] = 1;//源点已经确定好最短路径就是本身 TimeS[sourceV1] = 1; for (int i = 0; i < N; ++i) { if (i != sourceV1)//先确定不是源点 { int minLength = 99999999; int minLengthIndex = 0; for (int j = 0; j < N; ++j) { if (LengthS[j] == 0 && lengthDis[j] < minLength) { minLength = lengthDis[j]; minLengthIndex = j; } } LengthS[minLengthIndex] = 1; for (int j = 0; j < N; ++j) { if (j != sourceV1) { if (minLength + streetLength[minLengthIndex][j] < lengthDis[j]) { lengthDis[j] = minLength + streetLength[minLengthIndex][j]; lengthPos[j] = minLengthIndex; timeDis[j] = timeDis[minLengthIndex] + streetTime[minLengthIndex][j]; } else if (minLength + streetLength[minLengthIndex][j] == lengthDis[j] && timeDis[minLengthIndex] + streetTime[minLengthIndex][j] < timeDis[j]) {//如果路径相同,则依赖于时间同时少的,所以放在timeDis后面 lengthDis[j] = minLength + streetLength[minLengthIndex][j]; lengthPos[j] = minLengthIndex; timeDis[j] = timeDis[minLengthIndex] + streetTime[minLengthIndex][j]; } } } } } //--最短路径上节点数目 int NumberOfNode[501]; //将timeDis重新初始化,再一次迪杰斯特拉,根据路径点数量求最短时间 for (int i = 0; i < N; ++i) { if (i != sourceV1)//先确定不是源点 { timeDis[i] = streetTime[sourceV1][i]; } timePos[i] = -1; NumberOfNode[i] = 1; } //第二次迪杰斯特拉 for (int i = 0; i < N; ++i) { if (i != sourceV1)//先确定不是源点 { int minTime = 99999999; int minTimeIndex = 0; for (int j = 0; j < N; ++j) { if (TimeS[j] == 0 && timeDis[j] < minTime) { minTime = timeDis[j]; minTimeIndex = j; } } TimeS[minTimeIndex] = 1; for (int j = 0; j < N; ++j) { if (j != sourceV1) { if (minTime + streetTime[minTimeIndex][j] < timeDis[j]) { timeDis[j] = minTime + streetTime[minTimeIndex][j]; timePos[j] = minTimeIndex; NumberOfNode[j] = NumberOfNode[minTimeIndex] + 1; } else if (minTime + streetTime[minTimeIndex][j] == timeDis[j] && NumberOfNode[minTimeIndex] + 1 < NumberOfNode[j]) { timeDis[j] = minTime + streetTime[minTimeIndex][j]; timePos[j] = minTimeIndex; NumberOfNode[j] = NumberOfNode[minTimeIndex] + 1; } } } } } vector<int>shortLengthPos, shortTimePos; int temp_pos = destinationV2; shortLengthPos.push_back(temp_pos); while (lengthPos[temp_pos] != -1) { temp_pos = lengthPos[temp_pos]; shortLengthPos.push_back(temp_pos); } shortLengthPos.push_back(sourceV1); //----- temp_pos = destinationV2; shortTimePos.push_back(temp_pos); while (timePos[temp_pos] != -1) { temp_pos = timePos[temp_pos]; shortTimePos.push_back(temp_pos); } shortTimePos.push_back(sourceV1); if(pathIsSame(shortLengthPos, shortTimePos)) { cout << "Distance = " << lengthDis[destinationV2] << "; "; }else { cout << "Distance = " << lengthDis[destinationV2] << ":"; for (auto it = shortLengthPos.end() - 1; it > shortLengthPos.begin(); --it) { cout << " " << *it << " ->"; } cout << " " << *(shortLengthPos.begin()) << endl; } cout << "Time = " << timeDis[destinationV2] << ":"; for (auto it = shortTimePos.end() - 1; it > shortTimePos.begin(); --it) { cout << " " << *it << " ->"; } cout << " " << *(shortTimePos.begin()) << endl; }
相关文章推荐
- PAT 1030 Travel Plan(单源最短路径+优化Dijkstra)
- PAT 1003 Emergency(单源最短路径+Dijkstra)
- Dijkstra单源最短路径,POJ(2387)
- 单源最短路径问题[Dijkstra实现]
- Dijkstra单源最短路径算法
- 解题报告-HDOJ-1874(单源最短路径——Dijkstra)
- Dijkstra不能得到含有负权边图的单源最短路径
- 贪心算法 最小生成树prim与单源最短路径dijkstra
- 单源最短路径<Dijkstra>
- poj 3268 Silver Cow Party(单源最短路径Dijkstra·最小环)
- 贪心算法之最小生成树prim与单源最短路径dijkstra
- Dijkstra单源最短路径
- Dijkstra算法求单源最短路径Java实现
- Dijkstra求单源最短路径
- Dijkstra 单源最短路径
- 单源最短路径问题--Dijkstra
- 单源最短路径的Dijkstra 算法
- 贪心算法--Dijkstra单源最短路径
- 最短路径 (单源最短路径Dijkstra和任意两点最短路径Floyd) C实现
- 【图】单源最短路径dijkstra