题意:给定一个有向图,第一求最短的路径,如果最短路径不唯一,要求时间最短;第二求时间最短的路径,如果不唯一,要求经过顶点最少的的路径
思路:使用两次dijkstar算法分别计算最短的路径和最短的用时,当使用dijkstar的时候就直接可以计算出到终点的前驱数组,当需要遍历的时候直接遍历前驱数组直接就可以找到起点了;
代码:
#include<iostream>
#include<algorithm>
#include<vector>
const int INF = 99999999;
#define nodes 510
using namespace std;
int n = 0, m = 0, g[nodes][nodes], t[nodes][nodes], dis[nodes], Time[nodes], dispre[nodes], timepre[nodes], weight[nodes], Nodes[nodes], v, u;
vector<int> dispath, timepath;
int start, des;
bool vis[nodes];
void dfsdispath(int v) {//计算总的路径
dispath.push_back(v);
if (v == start)return;
dfsdispath(dispre[v]);
}
void dfstimepath(int v) {//计算总的时间最短的路径
timepath.push_back(v);
if (v == start)return;
dfstimepath(timepre[v]);
}
int main() {
fill(dis, dis + nodes, INF);
fill(Time, Time + nodes, INF);
// fill(weight, weight + nodes, INF);weight也可以不用初始化最大的,因为它只是用于当最短路径相等的时候比较时间的时候用的
fill(g[0], g[0] + nodes * nodes, INF);
fill(t[0], t[0] + nodes * nodes, INF);
cin >> n >> m;
int x, y, one, len, time;
for (int i = 0; i < m; i++) {
scanf("%d%d%d%d%d", &x, &y, &one, &len, &time);
g[x][y] = len;
t[x][y] = time;
if (one == 0) {
g[y][x] = len;
t[y][x] = time;
}
}
cin >> start >> des;
dis[start] = 0;//第一次dijstart算法,计算最短路径
// for (int i = 0; i < n; i++) {//其实不管3有没有前驱,当访问到3的时候加入了之后,直接返回了,没有影响
// dispre[i] = i;
// }
for (int i = 0; i < n; i++) {//第一次计算最段的路径
v = INF, u = -1;
for (int j = 0; j < n; j++) {
if (dis[j] < v && !vis[j]) {
v = dis[j], u = j;
}
}
if (u == -1)break;
vis[u] = true;
for (int j = 0; j < n; j++) {
if (!vis[j] && g[u][j] != INF) {
if (dis[u] + g[u][j] < dis[j]) {
dis[j] = dis[u] + g[u][j];//dis保存的是到每个顶点的最短距离
dispre[j] = u;//直接用dispre保存前驱
weight[j] = weight[u] + t[u][j];//保存weight(最短时间)只是用于比较,本质大小无所谓
}
else if (dis[u] + g[u][j] == dis[j] && weight[j] > weight[u] + t[u][j]) {
dispre[j] = u;
weight[j] = weight[u] + t[u][j];
}
}
}
}
dfsdispath(des);
fill(vis, vis + nodes, false);//第二次dijkstar算法,计算最短时间
Time[start] = 0;
for (int i = 0; i < n; i++) {
v = INF, u = -1;
for (int j = 0; j < n; j++) {
if (Time[j] < v && !vis[j]) {
v = Time[j], u = j;
}
}
if (u == -1)break;
vis[u] = true;
for (int j = 0; j < n; j++) {
if (!vis[j] && t[u][j] != INF) {
if (Time[u] + t[u][j] < Time[j]) {
Time[j] = Time[u] + t[u][j];
timepre[j] = (u);//保存时间最短的直接前驱
Nodes[j] = Nodes[u] + 1;//表示通过u到j更短,故更新到j的节点的个数
}
else if (Time[u] + t[u][j] == Time[j] && Nodes[j] > Nodes[u] + 1) {
timepre[j] = (u);
Nodes[j] = Nodes[u] + 1;
}
}
}
}
dfstimepath(des);
printf("Distance = %d", dis[des]);
if (dispath == timepath) {
printf("; Time = %d: ", Time[des]);
}
else {
printf(": ");
for (int i = dispath.size() - 1; i >= 0; i--) {
printf("%d", dispath[i]);
if (i != 0)printf(" -> ");
}
printf("\nTime = %d: ", Time[des]);
}
for (int i = timepath.size() - 1; i >= 0; i--) {
printf("%d", timepath[i]);
if (i != 0)printf(" -> ");
}
system("pause");
return 0;
}