数据结构实验之图论七:驴友计划(最短路径之Dijkstra算法)

https://blog.csdn.net/KO812605128/article/details/98987167 弗洛伊德(Floyd)算法
数据结构实验之图论七:驴友计划
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
做为一个资深驴友,小新有一张珍藏的自驾游线路图,图上详细的标注了全国各个城市之间的高速公路距离和公路收费情况,现在请你编写一个程序,找出一条出发地到目的地之间的最短路径,如果有多条路径最短,则输出过路费最少的一条路径。
Input

连续T组数据输入,每组输入数据的第一行给出四个正整数N,M,s,d,其中N(2 <= N <= 500)是城市数目,城市编号从0~N-1,M是城市间高速公路的条数,s是出发地的城市编号,d是目的地的城市编号;随后M行,每行给出一条高速公路的信息,表示城市1、城市2、高速公路长度、收费额,中间以空格间隔,数字均为整数且不超过500,输入数据均保证有解。
Output

在同一行中输出路径长度和收费总额,数据间用空格间隔。
Sample Input

1
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20

Sample Output

3 40

https://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html
算法实例

先给出一个无向图
在这里插入图片描述

用Dijkstra算法找出以A为起点的单源最短路径步骤如下
在这里插入图片描述首先,v0读入,进入第一个for循环,dsi[i]就是每个点到v0的距离,即到0的距离。之后0被标记,进入下一个循环。首先看j循环里面的,如果点没有访问并且dis[j],即各个点到0的距离,找到一个最小的,min记录,now记录j = 1值,之后1被标记,之后进入下一个循环,如果j没有标记并且now(即1)到j的有通路,之后进入下一个循环里,now,即1,没有标记的点到1的距离,如果j到now(即1)的距离加上dis[now](即起点到1的距离)如果小于dis[j](即j点到0的距离)【这个点与now点的路径+起点v0到now的最短路径 < 起点v0到j的最短路径】,另一种如果当距离相同时,花费少的优选。

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f

using namespace std;

int n, m;             ///顶点数,边数
int vis[1010];        ///点的访问情况
int money[1010][1010];///存放点与点之间的过路费
int mmap[1010][1010]; ///存放点与点之间的权值;

void dijkstra(int n, int v0, int vn)
{
    int dis[1010];    ///存放v0到vn的最短路径
    int mon[1010];
    for(int i = 0; i < n; i++)
    {
        dis[i] = mmap[v0][i];  ///每个点的最短路径都设为与起点相连边上的权值,(不与起点相连的点dist[]数组的值为MAX)
        mon[i] = money[v0][i]; ///每个点的过路费都初始化成与起点v0相连边上的费用。
    }
    vis[v0] = 1;///{
    dis[v0] = 0;///---->}对起点初始化,标记该点
    mon[v0] = 0;///{
    for(int i = 1; i < n; i++)///除了起点一共n-1个点
    {
        int min = INF;///先取一个无穷大的数,可以方便以后的替换其他的值;
        int now = v0; ///记录最短路径相关点的下标;
        for(int j = 0; j < n; j++)///找出与起始点相连最短的路径;
        {
            if(!vis[j] && dis[j] < min)///如果这个点没有被访问过,而且这个点的最短路径比min小;
                ///(这个循环的作用是找出与起点v0相连的点所形成的边,
                ///那个边的权值最小(最短路径最短))
            {
                min = dis[j];
                now = j;
            }
        }
        vis[now] = 1;///标记这个点
        for(int j = 0; j < n; j++)
        {
            if(!vis[j] && mmap[now][j] < INF)///如果这个点没被访问过。
                ///而且这个点j与点k之间存在边的话(mmap[k][j]<INF意思是k,j之间有边连接)
            {
                if(mmap[now][j] + dis[now] < dis[j])///这个点与k点的路径+起点v0到k的最短路径 < 起点v0到j的最短路径
                {
                    dis[j] = mmap[now][j] + dis[now];
                    mon[j] = mon[j] + money[now][j];
                }
                else if(dis[now] + mmap[now][j] == dis[j] && mon[now] + money[now][j] < mon[j])///路径相同,钱不同 ;
                    mon[j] = mon[j] + mmap[now][j];
            }
        }
    }
    cout<<dis[vn]<<" "<<mon[vn]<<endl;
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int v0, vn;///初始点
        cin>>n>>m>>v0>>vn;
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < n; j++)
            {
                if(i == j)
                    mmap[i][j] = 0;
                else
                    mmap[i][j] = INF;
            }
        }
        memset(vis, 0, sizeof(vis));
        int u, v, t, s;
        for(int i = 0; i < m; i++)
        {
            cin>>u>>v>>t>>s;
            mmap[u][v] = mmap[v][u] = t;
            money[u][v] = money[v][u] = s;
        }
        dijkstra(n, v0, vn);
    }
    return 0;
}

https://blog.csdn.net/weixin_39956356/article/details/80620667
这个是把路径都输出的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值