HDOJ 3790-最短路径问题

来源:互联网 发布:什么软件可以写日记 编辑:程序博客网 时间:2024/06/04 19:28

最短路径问题

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


题目链接:点击打开链接


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



分析:
用floyd超时了,于是改用迪杰斯特拉,但是本题需要考虑两个点,最重要的指标是距离,如果距离相等,就要考虑花费了,所以只要算的时候顺带将花费考虑到就行,具体在代码中详细的解释。


#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<queue>#include<stdlib.h>#define INF 0x3f3f3f3fusing namespace std;int Map1[1005][1005];///存放两点之间的距离int Map2[1005][1005];///存放两点之间的花费int n,m;   ///n个顶点,m条边int s,t;   ///起点s,终点tint dist[1005],cost[1005];  ///dist存放最小路径,cost存放最小花费void Dijkstra(int v)  ///狄克斯特拉求最短路{    int vis[1005];    ///用来设置标记的数组    int mindis,mincost,j,i,u;    for(i = 1; i <= n; i++)///对dist和cost以及vis进行初始化    {        dist[i] = Map1[v][i];        cost[i] = Map2[v][i];        vis[i] = 0;    }    vis[v] = 1;///将原点加入已求出最短路的集合    for(i=1;i<=n;i++)    {        mindis = INF;  ///另最小距离和最小花费为无穷大        mincost = INF;        for(j = 1; j <= n; j++)        {            if(vis[j] == 0)  ///如果这一点还未求出最小距离            {                ///如果原点到j的最小距离小于<mindis,或者等于mindis并且原点到j的最小花费<mincost,都要进行更新                ///因为距离是最重要的指标,如果距离相等,再考虑花费小的问题                if(dist[j]<mindis || (dist[j] == mindis && cost[j]<mincost))///                {                    u = j;                    mindis = dist[j];                    mincost = cost[j];                }            }        }        vis[u] = 1; ///将顶点u加入到已求出最短路的点集中        for(j = 1; j <= n; j++)  ///更新dist和cost数组            if(vis[j] == 0)  ///如果这一点没有求出最短路            {                if(Map1[u][j]!=INF)  ///如果u到j时有路的                {                    if(mindis+Map1[u][j]<dist[j])  ///加入源点到u在从u到j,比从原点直接到j的距离小                    {                        dist[j] = mindis+Map1[u][j];  ///更新原点到j的最小距离                        cost[j] = mincost+Map2[u][j];  ///最小花费对应更新                    }                    else if(mindis+Map1[u][j]==dist[j])  ///如果两者相等                    {                        if(mincost+Map2[u][j]<cost[j])  ///取花费较小者                            cost[j] = mincost + Map2[u][j];                    }                }            }    }}int main(){    int i,j,a,b,d,p;    while(~scanf("%d%d",&n,&m))    {        if(n == 0 && m == 0)            break;       ///对图进行初始化       for(i = 1; i <= n; i++)            for(j = 1; j <= n; j++)            {                if(i == j)                {                    Map1[i][j] = Map2[i][j] = 0;                }                else                    Map1[i][j] = Map2[i][j] = INF;            }        ///输入m条边        for(i = 0; i < m; i++)        {            scanf("%d%d%d%d",&a,&b,&d,&p);            if(d < Map1[a][b])///做最短路的题做多了,就知道可能两点之间有多条路            {                Map1[a][b] = Map1[b][a] = d;///在题目中距离因素更加重要,因此如果新输入的距离比原来的小,就更新数组的值                Map2[a][b] = Map2[b][a] = p;            }        }        scanf("%d%d",&s,&t);  ///输入起点和终点        Dijkstra(s);          ///调用函数求最短路和最小花费        printf("%d %d\n",dist[t],cost[t]);    }    return 0;}