- 题目描述:
-
给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
- 输入:
-
输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点t。n和m为0时输入结束。
(1<n<=1000, 0<m<100000, s != t)
-
输出:
-
输出 一行有两个数, 最短距离及其花费。
-
样例输入:
-
3 2
1 2 5 6
2 3 4 5
1 3
0 0
- 样例输出:
- 9 11
- 经典代码:
#include <stdio.h>
#define INT_MAX 0x7FFFFFFF
#define MAX_V 1001
#define MAX_E 1000
int
main()
{
int
n, m, d[MAX_V], p[MAX_V], visited[MAX_V], path[MAX_E][4], s, t, minPos;
while
(
scanf
(
"%d%d"
, &n, &m) != EOF)
{
if
(!n&&!m)
break
;
for
(
int
i = 0; i <= n; ++i)
{
d[i] = INT_MAX;
p[i] = INT_MAX;
visited[i] = 0;
}
for
(
int
i = 0; i < m; ++i)
scanf
(
"%d%d%d%d"
, &path[i][0], &path[i][1], &path[i][2], &path[i][3]);
scanf
(
"%d%d"
, &s, &t);
d[s] = 0; p[s] = 0; visited[s] = 1;
for
(
int
i = 0; i < m; ++i)
{
if
(path[i][0] == s)
{
d[path[i][1]] = path[i][2];
p[path[i][1]] = path[i][3];
}
else
if
(path[i][1] == s)
{
d[path[i][0]] = path[i][2];
p[path[i][0]] = path[i][3];
}
}
do
{
minPos = 0;
for
(
int
i = 1; i <= n; ++i)
{
if
(visited[i])
continue
;
if
(!minPos || d[i] < d[minPos] || (d[i] == d[minPos] && p[i] < p[minPos])) minPos = i;
}
if
(minPos)
{
int
a=minPos, b;
for
(
int
i = 0; i < m; i++)
{
if
(path[i][0] != a&&path[i][1] != a)
continue
;
if
(path[i][0] == a) b = path[i][1];
else
if
(path[i][1] == a) b = path[i][0];
if
(visited[b])
continue
;
if
(d[a] + path[i][2] < d[b]
|| d[a] + path[i][2] == d[b] && p[a]+path[i][3]<p[b])
{
d[b] = d[a] + path[i][2];
p[b] = p[a] + path[i][3];
}
}
visited[a] = 1;
}
}
while
(minPos);
printf
(
"%d %d
"
, d[t], p[t]);
}
return
0;
}