1. 程式人生 > >HDU - 最短路徑問題

HDU - 最短路徑問題

http://acm.hdu.edu.cn/showproblem.php?pid=3790

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Problem Description

給你n個點,m條無向邊,每條邊都有長度d和花費p,給你起點s終點t,要求輸出起點到終點的最短距離及其花費,如果最短距離有多條路線,則輸出花費最少的。

Input

輸入n,m,點的編號是1~n,然後是m行,每行4個數 a,b,d,p,表示a和b之間有一條邊,且其長度為d,花費為p。最後一行是兩個數 s,t;起點s,終點。n和m為0時輸入結束。
(1<n<=1000, 0<m<100000, s != t)

Output

輸出 一行有兩個數, 最短距離及其花費。

Sample Input

3 2
1 2 5 6
2 3 4 5
1 3
0 0

Sample Output

9 11

Problem solving report: 

Description: 最短路問題,給你n個點,m條無向邊,每條邊都有長度d和花費p,給你起點s終點t,要求輸出起點到終點的最短距離及其花費,如果最短距離有多條路線,則輸出花費最少的。

Problem solving: 在最短路的基礎上加一個記錄兩個點的花費額的陣列,只存兩個點最小的花費額,在利用最短邊鬆弛其它邊的時候,若鬆弛後的邊不變,鬆弛最小的花費額。

#include <stdio.h>
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;
}