迪杰斯特拉算法浅析

所谓的迪杰斯特拉算法,就是一个用来求一个图中某点到其它点的最短路径的算法。

大致方法:

  1. 遍历所有节点,找到离起点最近的一个点(那么这个点到起点的最小距离肯定是起点到这个点的这条边的权值),然后标记这个点被使用过了

  1. 以1中的那个点为中继,更新其它节点到起点的距离,也就是更新这个dis数组,怎么更新呢?当然是遍历所有点,如果这个点原先到起点的距离大于现在经过中继到起点的距离,那么就用这个较小的值更新dis数组

下面讲一下是怎么实现的。

  • 首先是采用邻接矩阵来储存图,有向图或者无向图均可,这里用有向图举例:

const int INF=1e7;
int mp[105][105];
int n;//节点个数
int m;//边的条数
cin>>n>>m;
//初始化边为无穷大
for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
        mp[i][j]=INF;
//输入边的数据
while(m--)
{
    cin>>u>>v>>w;
    mp[u][v]=min(mp[u][v],w);
    //若是无向图,则增加下面一行:
    //mp[v][u]=mp[u][v];
}
  • 接下来就是迪杰斯特拉算法辣:

void Dijkstra(int u)
{
    //首先是要开一个数组来储存我们的到某个点的最短距离
    int dis[105];
    //然后开一个数组用来记录这个点有没有被遍历
    bool visit[105];
    //初始化起点u到其他各个顶点的最短路径长度
    for(int i=1;i<=n;i++)
    {
        dis[i]=mp[u][i];
        visit[i]=false;
    }
    //起点到起点的距离当然是0咯:
    dis[u]=0;
    visit[u]=true;
    //循环寻找离起点最近的点:
    for(int i=1;i<=n;i++)
    {
        int min=INF;
        int t=u;
        for(int j=1;j<=n;j++) 
           if(!visit[j]&&dis[j]<min)
           {
                   t=j;
                   min=dis[j];
           }
        if(t==u) 
            return;//没有与起点连接的点了,跳出循环。 
        visit[t]=true;
        for(int j=1;j<=n;j++)//更新与中继点t邻接的点到起点u的距离 
           if(!visit[j]&&mp[t][j]<INF)
             if(dis[j]>(dis[t]+mp[t][j]))
                 dis[j]=dis[t]+mp[t][j];
    }
}

例题:

问题 H: 2.5 一场说走就走的旅行

内存限制:128 MB时间限制:1.000 S评测方式:文本比较命题人:admin提交:106解决:36

返回比赛提交提交记录侧边提交

题目描述

有一天,孩子回来对我说:“妈妈,听说马尔代夫很不错,放假了我想去玩。”

马尔代夫?我也想去!没有人不向往一场说走就走的旅行!

“其实我想去的地方很多,呼伦贝尔大草原、玉龙雪山、布达拉宫、艾菲尔铁塔……”小孩子还说着他感兴趣的地方。

于是我们拿出地图,标出想去的地点,然后计算最短路线,估算大约所需的时间,有了这张秘制地图,一场说走就走的旅行不是梦!

“哇,感觉我们像凡尔纳的《环游地球八十天》,好激动!可是老妈你也太 out 了,学计算机的最短路线你用手算?”

暴汗……,“小子你别牛,你知道怎么算?”

“呃,好像是叫什么迪科斯彻的人会算。”

哈哈,关键时刻还要老妈上场了!

输入

样例组数:

t ( 0 < t <= 10 )

城市的个数:

n ( 0 < n < 100 )

城市之间的路线的个数:

m ( 0 < m < 10000 )

请输入城市之间的路线以及距离:

( 0 < ui, vi, di <= 100 )

u1 v1 d1

u2 v2 d2

...

ui vi di

请输入小明所在的位置:

l ( 0 < l < 100 )

输出

小明到各个城市的最短距离;

l1 l2 ... ln (若某城市无法达到则输出impossible)

样例输入 复制
1
5 
11 
1 5 12 
5 1 8 
1 2 16 
2 1 29 
5 2 32 
2 4 13 
4 2 27 
1 3 15 
3 1 21 
3 4 7 
4 3 19 
5
样例输出 复制
8 24 23 30 0
#include<bits/stdc++.h>
using namespace std;
const int INF=1e7;//初始化无穷大为10000000
int mp[105][105];
int dist[105],n,m;
bool flag[105];//如果flag[i]等于true,说明顶点i已经加入到集合S;否则顶点i属于集合V-S.

void Dijkstra(int u)
{
    for(int i=1;i<=n;i++)
    {
        dist[i]=mp[u][i];//初始化源点u到其他各个顶点的最短路径长度。
        flag[i]=false;
    }
    dist[u]=0;
    flag[u]=true;//初始时,集合s中只有一个元素:源点u。 
    for(int i=1;i<=n;i++)
    {
        int min=INF;
        int t=u;
        for(int j=1;j<=n;j++)//在集合V-S中寻找距离源点u最近的顶点t。 
           if(!flag[j]&&dist[j]<min)
           {
                   t=j;
                   min=dist[j];
           }
        if(t==u) 
            return;//找不到t,跳出循环。 
        flag[t]=true;//否则,将t加入集合。
        for(int j=1;j<=n;j++)//更新集合V-S中与t邻接的顶点到源点u的距离 
           if(!flag[j]&&mp[t][j]<INF)//!flag[j]表示j在V-S中 
             if(dist[j]>(dist[t]+mp[t][j]))
                 dist[j]=dist[t]+mp[t][j];
    }
} 
int main()
{
    int t;
    cin>>t;
    while(t--)
    { 
        int u,v,w,st;
        cin>>n;
        cin>>m;
        for(int i=1;i<=n;i++)
           for(int j=1;j<=n;j++)
               mp[i][j]=INF;
        while(m--)
        {
            cin>>u>>v>>w;
            mp[u][v]=min(mp[u][v],w);
        }
        cin>>st;
        Dijkstra(st);
        for(int i=1;i<=n;i++)
        {
            if(dist[i]==INF)
                   cout<<"impossible"<<" ";
        else
           cout<<dist[i]<<" ";
        }
        cout<<endl;
    }
    return 0;
} 
  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嗯嗯你说的对

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值