PAT 1111 —— Online Map(Dijkstra單源最短路徑)
阿新 • • 發佈:2018-11-09
題目注意事項:
迪傑斯特拉兩次:
- 第一次求最短的路程長度【順便記錄時間用時,以判斷長度相同的時候選擇時間短的】
- 第二次求最短的路程時間【順便記錄到達每個點的最短路徑所需要的點數,以判斷時間相同時候選擇點數少的】【注意:第一次求得時間記錄需要重新初始化以免錯誤】
直接通過 vector < int > 判斷最終兩條路徑是否重合
#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;
}