HDU 3790.最短路径问题【最短路径Dijkstra算法】【4月14】

最短路径问题

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 20635    Accepted Submission(s): 6118


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
 
题目的裸地Dijkstra算法,但是需要在输入的时候保存最优的。如果两点之间多条边,保存最短边;两边同长,保存价值小的边。再做Dijkstra算法时也要保存价值。代码如下:

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
const int MAXN = 1005;
int dist[MAXN], c[MAXN], cost[MAXN][MAXN], len[MAXN][MAXN], vt[MAXN];
int n, m, s, t, a, b, d, p;
void Dijkstra(int root, int finish)
{
    memset(vt, 0, sizeof(vt));
    for(int i = 1;i <= n; ++i)
    {
        c[i] = 0x7FFFFFFF;
        dist[i] = 0x7FFFFFFF;
    }
    dist[root] = c[root] = 0;
    vt[root] = 1;
    for(int i = 1;i <= n; ++i)
    {
        int minx = 0x7FFFFFFF;
        for(int j = 1;j <= n; ++j)
        {
            if(vt[j] == 1) continue;
            if(len[root][j] == 0x7FFFFFFF) continue;
            if(dist[j] > dist[root] + len[root][j])
            {
                dist[j] = dist[root] + len[root][j];
                c[j] = c[root] + cost[root][j];
            }
            else if(dist[j] == dist[root] + len[root][j])//路径同长,要价值小的
            {
                if(c[j] > c[root] + cost[root][j])
                {
                    c[j] = c[root] + cost[root][j];
                }
            }
        }
        for(int j = 1;j <=  n; ++j)
        {
            if(vt[j] == 0 && dist[j] < minx)
            {
                root = j;
                minx = dist[j];
            }
        }
        vt[root] = 1;
    }
    cout << dist[finish] <<" "<< c[finish] << endl;
}
int main()
{
    while(scanf("%d %d", &n, &m) == 2 && n && m)
    {
        for(int i = 1;i <= n; ++i)
        for(int j = 1;j <= n; ++j)
            len[i][j] = 0x7FFFFFFF;
        for(int i = 1;i <= m; ++i)
        {
            scanf("%d %d %d %d", &a, &b, &d, &p);
            if(d < len[a][b])//两点之间多条边,保留短的
            {
                len[a][b] = len[b][a] = d;
                cost[a][b] = cost[b][a] = p;
            }
            else if(d == len[a][b])//边同长,保留价值小的
            {
                if(p < cost[a][b]) cost[a][b] = cost[b][a] = p;
            }
        }
        scanf("%d %d", &s, &t);
        Dijkstra(s, t);
    }
    return 0;
}



你可能感兴趣的:(C++,算法,ACM,最短路径,dijkstra)