Description
做为一个资深驴友,小新有一张珍藏的自驾游线路图,图上详细的标注了全国各个城市之间的高速公路距离和公路收费情况,现在请你编写一个程序,找出一条出发地到目的地之间的最短路径,如果有多条路径最短,则输出过路费最少的一条路径。
Input
连续T组数据输入,每组输入数据的第一行给出四个正整数N,M,s,d,其中N(2 <= N <= 500)是城市数目,城市编号从0~N-1,M是城市间高速公路的条数,s是出发地的城市编号,d是目的地的城市编号;随后M行,每行给出一条高速公路的信息,表示城市1、城市2、高速公路长度、收费额,中间以空格间隔,数字均为整数且不超过500,输入数据均保证有解。
Output
在同一行中输出路径长度和收费总额,数据间用空格间隔。
Sample
Input
1
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20
Output
3 40
Hint
本文提供多个解析选择适合自己的食用!
Floyd - Warshall(弗洛伊德算法、啊哈算法)
啊哈算法中的Dijkstra算法
ACM_最短路讲解
//Floyd
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
const int N = 555;
int G[N][N];//记录长度
int P[N][N];//记录花费
void init(int n)//初始化
{
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
if(i == j)
G[i][j] = 0;
else
G[i][j] = INF;
}
}
}
void Floyd(int n, int s, int d)
{
for(int k = 0; k < n; k++)
{
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
if(G[i][j] > G[i][k] + G[k][j])
{
G[i][j] = G[i][k] + G[k][j];
P[i][j] = P[i][k] + P[k][j];
}
else if(G[i][j] == G[i][k] + G[k][j])
{
P[i][j] = min(P[i][j], P[i][k] + P[k][j]);
}
}
}
}
cout << G[s][d] << ' ' << P[s][d] << endl;
}
int main()
{
int t;
cin >> t;
while(t--)
{
int n, m, s, d;
cin >> n >> m >> s >> d;
init(n);
while(m--)
{
int u, v, len, value;
cin >> u >> v >> len >> value;
G[u][v] = G[v][u] = len;
P[u][v] = P[v][u] = value;
}
Floyd(n, s, d);
}
return 0;
}
// Dijkstra
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
const int N = 550;
int mp[N][N];
int book[N];
int money[N][N];
int dist[N];
int mon[N];//接近于dist数组的用法,起到暂时记录的作用
void Dijkstra(int n, int s, int d)
{
int i, j, v, minn, u = 0;
for(i = 0; i < n; i++)
{
dist[i] = mp[s][i];//初始化dist数组,这里是s号顶点到其余各顶点的初始路程
mon[i] = money[s][i];//初始化mon数组,这里是s号顶点到其余各顶点的初始花费
}
dist[s] = 0;
book[s] = 1;
mon[s] = 0;
//Dijkstra核心语句
for(i = 1; i < n; i++)
{
//首先找到距离s点最近的顶点
minn = INF;
for(j = 0; j < n; j++)
{
if(minn > dist[j] && !book[j])
{
minn = dist[j];
u = j;//记录下这个顶点
}
}
book[u] = 1;
for(v = 0; v < n; v++)
{
if(mp[u][v] < INF && ! book[v])
{
if(dist[v] > dist[u] + mp[u][v])//如果从s到v的距离大于s到u + u到v的距离,那么就做替换
{
dist[v] = dist[u] + mp[u][v];
mon[v] = mon[u] + money[u][v];
}
else if(dist[v] == dist[u] + mp[u][v])//如果从s到v的距离和s到u + u到v的距离相等,就需要比较钱数
{
if(mon[v] > mon[u] + money[u][v])//同上
{
mon[v] = mon[u] + money[u][v];
}
}
}
}
}
cout << dist[d] << ' ' << mon[d] << endl;
}
int main()
{
int t, u, v, n, m, s, d, len, cost;
scanf("%d", &t);
while(t--)
{
scanf("%d %d %d %d",&n,& m, &s, &d);
memset(book, 0, sizeof(book));//初始化
memset(mp, INF, sizeof(mp));
for(int i = 0; i < n;i++)
{
mp[i][i] = 0;
}
while(m--)
{
scanf("%d %d %d %d",&u, &v, &len, &cost);
mp[u][v] = mp[v][u] = len;
money[u][v] = money[v][u] = cost;
}
Dijkstra(n, s, d);
}
return 0;
}