题意:输出最短路径,若最短路径相同,则输出代价最小的路径。
思路:迪杰斯特拉算法,用path数组记录最短路径,path[a] = b,表示从源s到b的最短路径中,最后一跳是通过a到b的。故输出时,应该用栈将b入栈后,依次将path[]数组从后往前遍历进栈。然后输出栈即可。
#include <iostream>
#include <vector>
#include <cstring>
#include <stack>
using namespace std;
struct Node
{
int next, dis, cost;
};
vector<Node> edges[501];
bool visited[501];
int dist[501];
int cost[501]; //记录花费
int path[501]; //记录路径
void print(int d)
{
stack<int> S;
S.push(d);
int pre = path[d];
while(pre != -1)
{
S.push(pre);
pre = path[pre];
}
while(!S.empty())
{
cout << S.top() << " ";
S.pop();
}
}
void Dij(int n, int s)
{
memset(visited, 0 , sizeof(visited));
for(int i = 0; i < n; i++)
{
dist[i] = -1;
cost[i] = 0;
path[i] = -1;
}
visited[s] = true;
dist[s] = 0;
int newp = s;
for(int i = 0; i < n-1; i++)
{
//松弛操作
for(int j = 0; j < edges[newp].size(); j++)
{
int next = edges[newp][j].next;
int len = edges[newp][j].dis;
int weight = edges[newp][j].cost;
//最短路径不止一条
if(dist[next] == dist[newp]+len)
{
if(cost[next] > cost[newp] + weight)
{
cost[next] = cost[newp] + weight;
path[next] = newp;
}
}
if(dist[next] == -1 || dist[newp]+len < dist[next])
{
dist[next] = dist[newp] + len;
cost[next] = cost[newp] + weight;
path[next] = newp;
}
}
//找下一个newp
int min = 111111111;
for(int j = 0; j < n; j++)
{
if(visited[j] || dist[j] == -1)
continue;
if(dist[j] < min)
{
min = dist[j];
newp = j;
}
}
visited[newp] = true;
}
}
int main()
{
int n, m, s, d;
cin >> n >> m >> s >> d;
int a, b, x, y;
for(int i = 0; i < m; i++)
{
Node tmp;
cin >> a >> b >> x >> y;
tmp.next = b, tmp.dis = x, tmp.cost = y;
edges[a].push_back(tmp);
tmp.next = a;
edges[b].push_back(tmp);
}
Dij(n, s);
print(d);
cout << dist[d] << " " << cost[d] << endl;
return 0;
}