A traveler's map gives the distances between cities along the highways, together with the cost of each highway. Now you are supposed to write a program to help a traveler to decide the shortest path between his/her starting city and the destination. If such a shortest path is not unique, you are supposed to output the one with the minimum cost, which is guaranteed to be unique.
Input Specification:
Each input file contains one test case. Each case starts with a line containing 4 positive integers N, M, S, and D, where N (≤500) is the number of cities (and hence the cities are numbered from 0 to N−1); M is the number of highways; S and D are the starting and the destination cities, respectively. Then M lines follow, each provides the information of a highway, in the format:
City1 City2 Distance Cost
where the numbers are all integers no more than 500, and are separated by a space.
Output Specification:
For each test case, print in one line the cities along the shortest path from the starting point to the destination, followed by the total distance and the total cost of the path. The numbers must be separated by a space and there must be no extra space at the end of output.
Sample Input:
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20
Sample Output:
0 2 3 3 40
#include <cstdio>
#include <vector>
using namespace std;
const int MAX = 5001;
const int INF = 100000001;
struct Node
{
//下一条邻接边 本条邻接边所指向的点 两点路径 两点消费
int next,to,len,consume;
}e[MAX];
//N - 城市数 M - 路线数 起始城市 目标城市
int N,M,StartCity,AimCity;
vector<int> pre[MAX];//存储最优路径
int vis[MAX] = {false};//标志
int d[MAX];//存储路径长度
int head[MAX];
int cnt = 0;
int optvalue = INF;//最终最优路径的花费
vector<int> path,tempath;//最终路径 临时路径
//构建邻接表
void add(int x,int y,int length,int con){
e[cnt].next = head[x];
e[cnt].to = y;
e[cnt].len = length;
e[cnt].consume = con;
head[x] = cnt;
cnt++;
}
//迪杰斯特拉找最短路径
void Dijkstra(){
fill(d,d + MAX,INF);//开始将路径都填充满 最大值
d[StartCity] = 0;//开始节点距离自己为0
for(int i = 0;i < N;i++){
int u = -1,min = INF;
for(int j = 0;j < N;j++){//寻找下一个最短的路径
if(vis[j] == false && d[j] < min){
min = d[j];
u = j;
}
}
if(u == -1)return;//无法继续寻找 结束
vis[u] = true;//标志已访
for(int j = head[u];j != -1;j = e[j].next){
if(vis[e[j].to] == false && d[u] + e[j].len < d[e[j].to]){//寻找到一条更短的路径时
d[e[j].to] = d[u] + e[j].len;
pre[e[j].to].clear();//清空原有最短路径
pre[e[j].to].push_back(u);
}else if(vis[e[j].to] == false && d[u] + e[j].len == d[e[j].to]){//寻找到一天相同长短的路径时
d[e[j].to] = d[u] + e[j].len;
pre[e[j].to].push_back(u);//增添一条最短路径
}
}
}
}
//深搜寻找花费更优路径
void DFS(int v){//v 当前节点
if(v == StartCity){
tempath.push_back(v);
int value = 0;//路径的花费
//计算这条路径的花费
//注意 i 开始为 1 (i > 0 时 i 与 i - 1 已经包含了到 0 的情况 而且 否则容易数组出界)
for(int i = 1;i < tempath.size();i++){
for(int j = head[tempath[i]];j != -1;j = e[j].next){
if(e[j].to == tempath[i - 1])value += e[j].consume;
}
}
if(value < optvalue){
//记录目前的最优路径
optvalue = value;
path = tempath;
}
tempath.pop_back();
return;//结束这次递归
}
tempath.push_back(v);
for(int i = 0;i < pre[v].size();i++){
DFS(pre[v][i]);//深搜寻找
}
tempath.pop_back();//v节点搜索完
}
int main(int argc, char const *argv[]) {
scanf("%d%d%d%d",&N,&M,&StartCity,&AimCity);
fill(head,head + MAX,-1);//将head填满 -1
for(int i = 0;i < M;i++){
int x,y,length,con;
scanf("%d%d%d%d",&x,&y,&length,&con);
//构建邻接表 无向图
add(x,y,length,con);
add(y,x,length,con);
}
Dijkstra();
DFS(AimCity);//深搜最优
//输出路径经过的点
for(int i = path.size() - 1;i >= 0;i--){
printf("%d ",path[i]);
}
printf("%d %d",d[AimCity],optvalue);//输出最短距离 和 最短距离的最小花费
return 0;
}