一、题目概述
求解两条路径:
1、源点、汇点间最短距离路径,若路经距离相同,选择耗时更短者。
2、源点、汇点间耗时最短路径,若路径耗时相同,选择路线上结点更少者。
二、思路
两次Dijkstra算法。
代码量较大,注意不要出错。
三、代码
#include <cstdio>
#include <vector>
using namespace std;
#define INF 0x7FFFFFFF
int main()
{
int N, M, c1, c2;
scanf("%d %d", &N, &M);
vector<vector<int>> D(N, vector<int>(N, INF)), T(N, vector<int>(N, INF));
vector<int> vset_1(N, 0), vset_2(N, 0), dist(N, INF), time_1(N, INF), time_2(N, INF), cnt(N, 0), pre_1(N, -1), pre_2(N, -1), path_1, path_2;
for(int i = 0, v1, v2, tag, d, t; i < M; ++i)
{
scanf("%d %d %d %d %d", &v1, &v2, &tag, &d, &t);
D[v1][v2] = d;
T[v1][v2] = t;
if(!tag)
{
D[v2][v1] = d;
T[v2][v1] = t;
}
}
scanf("%d %d", &c1, &c2);
dist[c1] = time_1[c1] = time_2[c1] = 0;
for(int i = 0, Min, v; i < N; ++i)
{
Min = INF;
for(int j = 0; j < N; ++j)
if(!vset_1[j] && dist[j] < Min)
{
Min = dist[j];
v = j;
}
if(Min == INF)
break;
vset_1[v] = 1;
for(int j = 0; j < N; ++j)
if(D[v][j] != INF)
if(dist[v] + D[v][j] < dist[j] || (dist[v] + D[v][j] == dist[j] && time_1[v] + T[v][j] < time_1[j]))
{
dist[j] = dist[v] + D[v][j];
time_1[j] = time_1[v] + T[v][j];
pre_1[j] = v;
}
}
for(int i = c2; i != -1; i = pre_1[i])
path_1.push_back(i);
for(int i = 0, Min, v; i < N; ++i)
{
Min = INF;
for(int j = 0; j < N; ++j)
if(!vset_2[j] && time_2[j] < Min)
{
Min = time_2[j];
v = j;
}
if(Min == INF)
break;
vset_2[v] = 1;
for(int j = 0; j < N; ++j)
if(T[v][j] != INF)
if(time_2[v] + T[v][j] < time_2[j] || (time_2[v] + T[v][j] == time_2[j] && cnt[v] + 1 < cnt[j]))
{
time_2[j] = time_2[v] + T[v][j];
cnt[j] = cnt[v] +1;
pre_2[j] = v;
}
}
for(int i = c2; i != -1; i = pre_2[i])
path_2.push_back(i);
if(path_1 != path_2)
{
printf("Distance = %d: ", dist[c2]);
for(int i = path_1.size() - 1; i >= 0; --i)
printf("%d%s", path_1[i], i ? " -> ":"\n");
printf("Time = %d: ", time_2[c2]);
for(int i = path_2.size() - 1; i >= 0; --i)
printf("%d%s", path_2[i], i ? " -> ":"");
return 0;
}
printf("Distance = %d; Time = %d: ", dist[c2], time_2[c2]);
for(int i = path_2.size() - 1; i >= 0; --i)
printf("%d%s", path_2[i], i ? " -> ":"");
}