Dijkstra 最短路径算法详解 无向图

对于最短路径问题,这里介绍一种O(N^2)的求解方法。

对于求最短路径的问题一般都会给出一幅图,或者边与边的关系。如上图。

假设我们起点是A,我们要求到F的最短距离,我们会怎么做?

首先,因为A是起点,所以我们把对于每个点都有个参数,相对于A的距离,默认除了A到A为0,其他都是无穷大。

从起点A开始,我们更新与A相连通的点到A的距离,并把A点标记。如图:

我们遍历一次所有点与A的距离,找到最小的,这里是点B。

以它为起点,把它周围未被标记的点拿来做比较,显然,像F这种没有与A练过的点,当前距离就会变成min(dis[B]+maze[B][F],INF),就是B到起点的距离加上BF之间的距离。而像c这种与A直接相连的点,当前距离就会变成min(dis[B]+maze[B][C],dis[c]),所以按照我们每次只需要比较当前点到当前状态起点的和与当前点到起点的距离就可以了。

然后我们遍历发现,当前未被标记且到起点距离最小点的点是C点。我们更新连接了C的所有点。同样利用上面的min公式。

同理,更新D点的邻点。

再把更新E点的邻点。

最后再更新F点。发现F点周围所有点都被标记了,不做更新。

再遍历,发现图中所有点都被遍历了,算法结束。

这个时候,我们已经求出了所有点到起点的最小距离。

可以直接输出dis[F]求得A到F的最短路径。

注意:

上面的图重点是看每次变化找的起点和与出发点路径的变化。

当前起点是当前未被标记且到出发点距离最近的点。

更新的点都是与该起点直接相连并未被标记的点。

因为并没有无穷大这个数,所以我们把INF设为一个我们计算不能到达的数,这里的数接近int的上限,可以近似看作正无穷。

参考代码如下:

#include"iostream"
#include"cstring"
#include"cstdio"

using namespace std;
#define INF 0x7f7f7f7f

const int N = 105; //点的个数上限

int maze[N][N];
int dis[N];
bool vis[N];

//点的个数和边的条数
int n,m;

void init()
{
    memset(maze,INF,sizeof(maze));
    memset(dis,INF,sizeof(dis));
    memset(vis,false,sizeof(vis));
}

void dijkstra(int st)
{
    dis[st]=0;
    for(int i=1; i<=n; i++)
    {
    //找到和起点距离最短的点
        int minx=INF;
        int minmark;
        for(int j=1; j<=n; j++)
        {
            if(vis[j]==false&&dis[j]<=minx)
            {
                minx=dis[j];
                minmark=j;
            }
        }
        //并标记
        vis[minmark]=true;
        //更新所有和它连接的点的距离
        for(int j=1; j<=n; j++)
        {
            if(vis[j]==false&&dis[j]>dis[minmark]+maze[minmark][j])
                dis[j]=dis[minmark]+maze[minmark][j];
        }
    }
}

int main()
{
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        if(n==0&&m==0) break;
        //每组数据都要初始化
        init();
        for(int i=1; i<=m; i++)
        {
            int x,y,len;
            scanf("%d %d %d",&x,&y,&len);
            if(x!=y&&maze[x][y]>len)
            {
                maze[y][x]=len;
                maze[x][y]=len;
            }
        }
        //以1为起点跑一次dij
        dijkstra(1);
        //输出到n的距离
        printf("%d\n",dis[n]);
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-04 12:01:29

Dijkstra 最短路径算法详解 无向图的相关文章

最短路算法 :Bellman-ford算法 &amp; Dijkstra算法 &amp; floyd算法 &amp; SPFA算法 详解

 本人QQ :2319411771   邮箱 : [email protected] 若您发现本文有什么错误,请联系我,我会及时改正的,谢谢您的合作! 本文为原创文章,转载请注明出处 本文链接   :http://www.cnblogs.com/Yan-C/p/3916281.html . 很早就想写一下最短路的总结了,但是一直懒,就没有写,这几天又在看最短路,岁没什么长进,但还是加深了点理解. 于是就想写一个大点的总结,要写一个全的. 在本文中因为邻接表在比赛中不如前向星好写,而且前向星效率并

最短路径问题---Floyd算法详解

前言 Genius only means hard-working all one's life. Name:Willam Time:2017/3/8 1.最短路径问题介绍 问题解释: 从图中的某个顶点出发到达另外一个顶点的所经过的边的权重和最小的一条路径,称为最短路径 解决问题的算法: 迪杰斯特拉算法(Dijkstra算法) 弗洛伊德算法(Floyd算法) SPFA算法 之前已经对Dijkstra算法做了介绍(不懂的可以看这篇博客:Dijkstra算法详解),所以这篇博客打算对Floyd算法做

最短路SPFA 算法详解

最短路SPFA 算法详解 适用范围:给定的图存在负权边,这时类似Dijkstra等算法便没有了用武之地,而Bellman-Ford算法的复杂度又过高,SPFA算法便派上用场了. 我们约定有向加权图G不存在负权回路,即最短路径一定存在.当然,我们可以在执行该算法前做一次拓扑排序,以判断是否存在负权回路,但这不是我们讨论的重点. 算法思想:我们用数组d记录每个结点的最短路径估计值,用邻接表来存储图G.我们采取的方法是动态逼近法:设立一个先进先出的队列用来保存待优化的结点,优化时每次取出队首结点u,并

Tarjan算法详解

Tarjan算法详解 [概念] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极大强连通子图,称为强连通分量(strongly connected components). 下图中,子图{1,2,3,4}为一个强连通分量,因为顶点1,2,3,4两两可达.{5},{6}也分别是两个强连通分量. [功能] Tarjan算法的用途之一是,求一个有向图G=(V,E)里极大强连

KM算法详解[转]

KM算法详解 原帖链接:http://www.cnblogs.com/zpfbuaa/p/7218607.html#_label0 阅读目录 二分图博客推荐 匈牙利算法步骤 匈牙利算法博客推荐 KM算法步骤 KM算法标杆(又名顶标)的引入 KM流程详解 KM算法博客推荐 0.二分图 二分图的概念 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V, E)是一个无向图.如果顶点集V可分割为两个互不相交的子集X和Y,并且图中每条边连接的两个顶点一个在X中,另一个在Y中,则称图G为二分图. 可以

EM算法(3):EM算法详解

目录 EM算法(1):K-means 算法 EM算法(2):GMM训练算法 EM算法(3):EM算法详解

[转] KMP算法详解

转载自:http://www.matrix67.com/blog/archives/115 KMP算法详解 如果机房马上要关门了,或者你急着要和MM约会,请直接跳到第六个自然段.    我们这里说的KMP不是拿来放电影的(虽然我很喜欢这个软件),而是一种算法.KMP算法是拿来处理字符串匹配的.换句话说,给你两个字符串,你需要回答,B串是否是A串的子串(A串是否包含B串).比如,字符串A="I'm matrix67",字符串B="matrix",我们就说B是A的子串.

[搜索]波特词干(Porter Streamming)提取算法详解(3)

 接上 [搜索]波特词干(Porter Streamming)提取算法详解(2) 下面分为5大步骤来使用前面提到的替换条件来进行词干提取. 左边是规则,右边是提取成功或者失败的例子(用小写字母表示). 步骤1 SSES -> SS                   caresses  ->  caress IES  -> I                          ponies    ->  poni ties      ->  ti SS   -> S

KMP算法详解(图示+代码)

算法过程非常绕,不要企图一次就能看明白,多尝试就会明白一些.下面试图用比较直观的方法解释这个算法,对KMP算法的解释如下: 1. 首先,字符串"BBC ABCDAB ABCDABCDABDE"的第一个字符与搜索词"ABCDABD"的第一个字符,进行比较.因为B与A不匹配,所以搜索词后移一位. 2. 因为B与A不匹配,搜索词再往后移. 3. 就这样,直到字符串有一个字符,与搜索词的第一个字符相同为止. 4. 接着比较字符串和搜索词的下一个字符,还是相同. 5. 直到字