http://acm.hdu.edu.cn/showproblem.php?pid=3790
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点。n和m为0时输入结束。
(1
输出 一行有两个数, 最短距离及其花费。
3 2
1 2 5 6
2 3 4 5
1 3
0 0
9 11
Description: 最短路问题,给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
Problem solving: 在最短路的基础上加一个记录两个点的花费额的数组,只存两个点最小的花费额,在利用最短边松弛其它边的时候,若松弛后的边不变,松弛最小的花费额。
#include
const int inf = 99999999;
int n, m, s, t, k, a, b, d, q, minn;
int vis[1010], dis[1010], map[1010][1010], cost[1010][1010];
int main()
{
while (scanf("%d%d", &n, &m), m + n)
{
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (i != j)
cost[i][j] = cost[j][i] = map[i][j] = map[j][i] = inf;
else cost[i][j] = cost[j][i] = map[i][j] = map[j][i] = 0;
for (int i = 0; i < m; i++)
{
scanf("%d%d%d%d", &a, &b, &d, &q);
if (map[a][b] > d)
{
map[a][b] = map[b][a] = d;
cost[a][b] = cost[b][a] = q;
}
else if (map[a][b] == d && cost[a][b] > q)
cost[a][b] = cost[b][a] = q;
}
scanf("%d%d", &s, &t);
for (int i = 1; i <= n; i++)
{
dis[i] = map[s][i];
vis[i] = 0;
}
vis[s] = 1;
for (int i = 1; i < n; i++)
{
minn = inf;
for (int j = 1; j <= n; j++)
{
if (!vis[j] && dis[j] < minn)
{
k = j;
minn = dis[j];
}
}
vis[k] = 1;
for (int j = 1; j <= n; j++)
{
if (map[k][j] < inf)
{
if (!vis[j] && dis[j] > dis[k] + map[k][j])
{
dis[j] = dis[k] + map[k][j];
cost[s][j] = cost[s][k] + cost[k][j];
}
else if (!vis[j] && dis[j] == dis[k] + map[k][j] && cost[s][j] > cost[s][k] + cost[k][j])
cost[s][j] = cost[s][k] + cost[k][j];
}
}
}
printf("%d %d\n", dis[t], cost[s][t]);
}
return 0;
}