- 题目描述:
-
给你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\n", d[t], p[t]);
}
return 0;
}