精华内容
下载资源
问答
  • 最小生成树的prim算法,克鲁斯卡尔算法 https://www.cnblogs.com/zhchoutai/p/8687614.html https://blog.csdn.net/gao506440410/article/details/81745875 最短路径的迪杰斯特拉算法,弗洛伊德算法 ...

    最小生成树的prim算法,克鲁斯卡尔算法 https://www.cnblogs.com/zhchoutai/p/8687614.html https://blog.csdn.net/gao506440410/article/details/81745875
    最短路径的迪杰斯特拉算法,弗洛伊德算法

    展开全文
  • 用java编写的迪杰斯特拉算法,求图中的最短路径问题。
  • 先上一个百度百科定义:迪杰斯特拉算法 --------------------------------------------------------------------------------------------------------分割线-------------------------------------

    前面转了两篇博客说了一下这个迪杰斯特拉算法,现在自己尝试总结一下。

    先上一个百度百科的定义:迪杰斯特拉算法

    --------------------------------------------------------------------------------------------------------分割线----------------------------------------------------------------------------------------------------------------

    首先,迪杰斯特拉算法是用来解决单源最短路经问题的,主要是通过边的松弛来实现。

    我们来看这个问题:


    这个问题求得是从1号顶点到达所有其他顶点的最短距离,我们用邻接矩阵来存储这个图,如下:


    我们用一个dis数组来存储从一号顶点到其他各个顶点的初始路径,如图


    先找一个离一号顶点最近的顶点,通过dis我们知道最近的顶点是2号顶点,从第2个顶点有两条边是2-->3和2-->4。先通过2-->3这个边看能否是从1到3的路程变短,也就是比较dis[3]与dis[2]+map[2][3]的大小,很明显dis[3]=12,而dis[2]+map[2][3]=10,所以我们把dis[3]的值更新为10,这个过程就是我们所说的“松弛”,同样对于2-->4,dis[4]的初始值为无穷大,而dis[2]+dis[2][4]=4,所以我们把dis[4]的值松弛为4,经过这一个松弛后,dis变成了:


    把已经找过的点进行标记,然后在剩下的3,4,5,6顶点钟找出离1号顶点最近的顶点,很明显最近的是4,然后根据上面的思路继续进行松弛,一直松弛到边完,这时dis变为


    整个过程用完整的代码来表示如下:

    #include <stdio.h>
    #include <string.h>
    #include <string>
    #include <iostream>
    #include <stack>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    const int inf=1<<29;
    int main()
    {
        int map[10][10],t1,t2,t3,min,u,n,m;
        int dis[10];
        int vis[10];
        scanf("%d%d",&n,&m);
        //初始化
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                if(i==j)
                    map[i][j]=0;
                else
                    map[i][j]=inf;
        //读入边
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d%d",&t1,&t2,&t3);
            map[t1][t2]=t3;
        }
        //初始化dis数组,表示1号顶点到其余各个顶点的最短路程
        for(int i=1; i<=n; i++)
            dis[i]=map[1][i];
        //初始化vis
        for(int i=1; i<=n; i++)
            vis[i]=0;
        vis[1]=1;//标记起始点1已经被访问过
        //迪杰斯特拉算法(Dijkstra)的核心内容
        for(int i=1; i<=n-1; i++) //因为松弛的是边数,所以是n-1
        {
            min=inf;
            for(int j=1; j<=n; j++)
            {
                if(vis[j]==0&&dis[j]<min)
                {
                    min=dis[j];
                    u=j;
                }
            }
            vis[u]=1;
            for(int v=1; v<=n; v++)
                if(map[u][v]<inf)
                    if(dis[u]+map[u][v]<dis[v])
                        dis[v]=dis[u]+map[u][v];
        }
        for(int i=1;i<=n;i++)
            printf("%d ",dis[i]);
        return 0;
    }
    
    给出一组样例进行测试:

    输入:

    6 9
    1 2 1
    1 3 12
    2 3 9
    2 4 3
    3 5 5
    4 3 4
    4 5 13
    4 6 15
    5 6 4

    输出:
    0 1 8 4 13 17

    利用邻接表,我们可以把时间复杂度优化到O(M+N)logN,以下是用邻接表来优化这个算法的代码:

    #include <stdio.h>
    #include <string.h>
    #include <string>
    #include <iostream>
    #include <stack>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    const int inf=0x3f3f3f3f;
    int u[10],v[10],w[10],first[10],next[10],dist[10],vis[10],n,m,k,minn;
    int main()
    {
        scanf("%d%d",&n,&m);
        //初始化
        for(int i=1; i<=n; i++)
            first[i]=-1;
        //读入边
        mem(dist,inf);
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d%d",&u[i],&v[i],&w[i]);
            next[i]=first[u[i]];
            first[u[i]]=i;
            if(u[i]==1)
                dist[v[i]]=w[i];//初始化dis数组,表示1号顶点到其余各个顶点的最短路程
        }
        //初始化vis
        for(int i=1; i<=n; i++)
            vis[i]=0;
        vis[1]=1;//标记起始点1已经被访问过
        dist[1]=0;
        //迪杰斯特拉算法(Dijkstra)的核心内容
        for(int i=1; i<=n-1; i++)
        {
            minn=inf;
            for(int j=1; j<=n; j++)
            {
                if(vis[j]==0&&dist[j]<minn)
                {
                    minn=dist[j];
                    k=j;
                }
            }
            vis[k]=1;
            for(int l=first[k]; l!=-1; l=next[l])
            {
                if(w[l]<inf)
                    if(dist[k]+w[l]<dist[v[l]])
                        dist[v[l]]=dist[k]+w[l];
            }
        }
        for(int i=1; i<=n; i++)
            printf("%d ",dist[i]);
        return 0;
    }






    展开全文
  • 图解最短路径迪杰斯特拉算法(Java实现)

    万次阅读 多人点赞 2019-05-10 20:04:43
    概述 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959...迪杰斯特拉算法采用是贪心策略,将Graph中节点集分为最短路径计算完成节点集S和未计算完成节点集T,每次将从T中挑选V0->Vt最小节点Vt加入...

    概述

    迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。迪杰斯特拉算法采用的是贪心策略,将Graph中的节点集分为最短路径计算完成的节点集S和未计算完成的节点集T,每次将从T中挑选V0->Vt最小的节点Vt加入S,并更新V0经由Vt到T中剩余节点的更短距离,直到T中的节点全部加入S中,它贪心就贪心在每次都选择一个距离源点最近的节点加入最短路径节点集合。迪杰斯特拉算法只支持非负权图,它计算的是单源最短路径,即单个源点到剩余节点的最短路径,时间复杂度为O(n²)。

    算法描述

    在有向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短值。

    算法流程

    本节将对算法流程进行模拟,设置Graph为包含7个顶点和9条边的有向无环图,源点为0,计算从源点0到剩余节点的最短路径,Graph如下:

    每个节点将维护shortest和visited两个数据结构,shortest存储v0到该节点的最短路径,visited存储v0到该节点的最短路径是否求出。S为已求出最短路径的节点,T为未求出最短路径的节点。源节点只允许将S中的节点作为中间节点来计算到达其它节点的最短路径,不允许将T中的节点作为中间节点来计算到达其它节点的最短路径。随着S中节点的增加,源节点可达的节点才会增加。初始状态下,源节点只可达节点1和节点3。

    算法步骤如下:

    1、将源节点(即节点0)加入S中,对shortest和visited数组进行更新。

    2、S中现有节点0,源节点可达T中的节点1和节点3,节点0->节点1距离为6,节点0->节点3距离为2,按距离从小到大排序,因此选择将节点3加入S中。更新源点将节点3作为中间节点到达其它节点的距离。

    3、S中现有节点0和节点3,源节点可达T中的节点1和4,节点0->节点1距离为6,节点0->节点4距离为7,按距离从小到大排序,因此选择将节点1加入S中。更新源点将节点1作为中间节点到达其它节点的距离。

    4、S中现有节点0、1、3,源节点可达T中的节点2、4、5,0->2距离为11,0->4距离为7,0->5距离为9,按距离从小到大排序,因此选择将节点4加入S中。更新源点将节点4作为中间节点到达其它节点的距离。

    5、S中现有节点0、1、3、4,源节点可达T中的节点2、5、6,0->2距离为11,0->5距离为9,0->6距离为8,按距离从小到大排序,因此选择将节点6加入S中。更新源点将节点6作为中间节点到达其它节点的距离。

    6、S中现有节点0、1、3、4、6,源节点可达T中的节点2、5,0->2距离为11,0->5距离为9,按距离从小到大排序,因此选择将节点5加入S中。更新源点将节点5作为中间节点到达其它节点的距离。

    7、T中只剩下节点2,0->2距离为11,将节点2加入S中。

    8、算法结束,源点到其它节点的最短路径都已依次求出。

    算法实现

    public class DijstraAlgorithm {
        //不能设置为Integer.MAX_VALUE,否则两个Integer.MAX_VALUE相加会溢出导致出现负权
        public static int MaxValue = 100000;
        
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            System.out.println("请输入顶点数和边数:");
            //顶点数
            int vertex = input.nextInt();
            //边数
            int edge = input.nextInt();
    
            int[][] matrix = new int[vertex][vertex];
            //初始化邻接矩阵
            for (int i = 0; i < vertex; i++) {
                for (int j = 0; j < vertex; j++) {
                    matrix[i][j] = MaxValue;
                }
            }
            for (int i = 0; i < edge; i++) {
                System.out.println("请输入第" + (i + 1) + "条边与其权值:");
                int source = input.nextInt();
                int target = input.nextInt();
                int weight = input.nextInt();
                matrix[source][target] = weight;
            }
    
            //单源最短路径,源点
            int source = input.nextInt();
            //调用dijstra算法计算最短路径
            dijstra(matrix, source);
        }
    
        public static void dijstra(int[][] matrix, int source) {
            //最短路径长度
            int[] shortest = new int[matrix.length];
            //判断该点的最短路径是否求出
            int[] visited = new int[matrix.length];
            //存储输出路径
            String[] path = new String[matrix.length];
    
            //初始化输出路径
            for (int i = 0; i < matrix.length; i++) {
                path[i] = new String(source + "->" + i);
            }
    
            //初始化源节点
            shortest[source] = 0;
            visited[source] = 1;
    
            for (int i = 1; i < matrix.length; i++) {
                int min = Integer.MAX_VALUE;
                int index = -1;
    
                for (int j = 0; j < matrix.length; j++) {
                    //已经求出最短路径的节点不需要再加入计算并判断加入节点后是否存在更短路径
                    if (visited[j] == 0 && matrix[source][j] < min) {
                        min = matrix[source][j];
                        index = j;
                    }
                }
    
                //更新最短路径
                shortest[index] = min;
                visited[index] = 1;
    
                //更新从index跳到其它节点的较短路径
                for (int m = 0; m < matrix.length; m++) {
                    if (visited[m] == 0 && matrix[source][index] + matrix[index][m] < matrix[source][m]) {
                        matrix[source][m] = matrix[source][index] + matrix[index][m];
                        path[m] = path[index] + "->" + m;
                    }
                }
    
            }
    
            //打印最短路径
            for (int i = 0; i < matrix.length; i++) {
                if (i != source) {
                    if (shortest[i] == MaxValue) {
                        System.out.println(source + "到" + i + "不可达");
                    } else {
                        System.out.println(source + "到" + i + "的最短路径为:" + path[i] + ",最短距离是:" + shortest[i]);
                    }
                }
            }
        }
    }

    样例输入:

    7 10

    0 1 6

    1 2 5

    0 3 2

    3 1 7

    3 4 5

    1 2 5

    1 5 3

    4 5 5

    5 4 2

    4 6 1

    0

    Q&A

    问:为什么迪杰斯特拉算法只支持非负权的图?

    答:迪杰斯特拉采用的贪心策略,S集合中是已经计算出最短路径的节点,T集合中是未计算出最短路径的节点。假设存在负权,源点为A,已经计算出A->B的最短路径为m,若下一次将C添加进已计算出最短路径的节点集合,而A->C=m,C->B=-1,则会出现A->B的更短路径A->C->B,但迪杰斯特拉不会对已经计算出最短路径的节点重新计算,因此无法更新最短路径,即负权的出现导致无法保证S中节点计算的是最短路径,已经固定dis的点可能会被其它dis大于它的点更新。

    问:为什么在代码实现中不能将节点之间不可达用Integer.MAX_VALUE代表?

    答:因为两个Integer.MAX_VALUE相加会溢出导致出现负权,所以最好设置为一个比较大且不容易相加溢出的数。

    问:迪杰斯特拉算法适用于什么场景?

    答:在有些算法书上说,迪杰斯特拉适用于DAG(有向无环图)。但是个人觉得,它所谓的“适用于”,或许只是说可以在DAG上使用,并不代表无向图不能使用,也不能代表有环图不能使用。从迪杰斯特拉的算法原理上来说,无向图是没有问题的,只需要给matrix[source][target]和matrix[target][source]赋上相同的权值,因为它每次只会根据到源点的距离,选取距离最近的一个节点加入,所以有没有方向都无所谓,算法只关注可达点的距离;至于有环图,它对每个节点的距离计算只用了一层遍历去做,并不会陷入死循环,也不会出现重复计算的问题。因此迪杰斯特拉算法是可以用在无向图和有环图中的,适合于求单源最短路径。

    展开全文
  • 这道题是无向无负边权问题,用迪杰斯特拉算法就能很好解决。如果不太懂迪杰斯特拉算法,可以看我另一篇博文: 迪杰斯特拉讲解 AC代码如下: #include using namespace std; const int INF = ...

    问题描述:

    As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the length of each road between any pair of cities are marked on the map. When there is an emergency call to you from some other city, your job is to lead your men to the place as quickly as possible, and at the mean time, call up as many hands on the way as possible.

    Input

    Each input file contains one test case. For each test case, the first line contains 4 positive integers: N (<= 500) - the number of cities (and the cities are numbered from 0 to N-1), M - the number of roads, C1 and C2 - the cities that you are currently in and that you must save, respectively. The next line contains N integers, where the i-th integer is the number of rescue teams in the i-th city. Then M lines follow, each describes a road with three integers c1, c2 and L, which are the pair of cities connected by a road and the length of that road, respectively. It is guaranteed that there exists at least one path from C1 to C2.

    Output

    For each test case, print in one line two numbers: the number of different shortest paths between C1 and C2, and the maximum amount of rescue teams you can possibly gather.\ All the numbers in a line must be separated by exactly one space, and there is no extra space allowed at the end of a line.

     

    这道题是无向无负边权的问题,用迪杰斯特拉算法就能很好的解决。如果不太懂迪杰斯特拉算法,可以看我的另一篇博文:

    迪杰斯特拉讲解

    AC代码如下:

    #include <bits/stdc++.h>
    
    using namespace std;
    const int INF = 10000000;           ///最大值
    const int maxv = 1000;          ///最大节点数
    int G[maxv][maxv];              ///邻接矩阵
    int d[maxv];        ///存放最短路径
    int weight[maxv];               ///点权重
    int vis[maxv] = {false};
    int w[maxv] ;
    ///邻接矩阵的深度优先遍历
    int n;
    int num[maxv] = {0};
    void Djskl(int s)
    {
        for(int i=0; i<maxv; i++)
            d[i] = INF;
        memset(w,0,sizeof(w));
        d[s] = 0;
        w[s] = weight[s];
        num[s] = 1;
        for(int i=0; i<n; i++)
        {
            int u = -1,MIN = INF;
            for(int j=0; j<n; j++)
            {
                if(vis[j] == false && d[j] < MIN)
                {
                    u = j;
                    MIN = d[j];
                }
            }
            if(u == -1)
                return ;
            vis[u] = true;
            for(int v = 0; v<n; v++)
            {
                if(vis[v] == false && G[u][v] != INF )
                {
                    if(d[u] + G[u][v] < d[v])
                    {
                        d[v] = d[u] + G[u][v];
                        if(w[u] + weight[v] > w[v] )
                        {
                            w[v] = w[u] + weight[v];
                        }
                        num[v] = num[u];
                    }
                    else if(d[u] + G[u][v] == d[v])
                    {
                        num[v] += num[u] ;
                        if(w[u] + weight[v] > w[v] )
                        {
                            w[v] = w[u] + weight[v];
                        }
                    }
                }
            }
        }
    }
    
    
    int main()
    {
        cin>>n;
        int m,s,dis;
        cin>>m>>s>>dis;
        for(int i=0; i<maxv; i++)
            for(int j=0; j<maxv; j++)
            {
                 G[i][j] = INF;
            }
        int u,v,wn;
        for(int i=0; i<n; i++)
        {
            int x;
            cin>>x;
            weight[i] = x;
        }
        for(int i=0; i<m; i++)
        {
            cin>>u>>v>>wn;
            G[u][v] = wn;
            G[v][u] = wn;
        }
        Djskl(s);
        cout<<num[dis]<<" ";
        cout<<w[dis]<<endl;
        return 0;
    }
    

     

    展开全文
  • 奇妙算法世界,单源最短路径迪杰斯特拉算法 今天我们要讲解内容是单源最短路径迪杰斯特拉算法。 一、问题描述 假期来临,小漫打算去海南旅行,如果出发地北京和目的地海南之间有多条路径,不同路径上有...
  • 迪杰斯特拉算法 弗洛伊德算法 1.最短路径 首先我们要清楚什么是最短路径,怎么样称为最短。 概念:从图中某个顶点出发到达另外一个顶点所经过权重(权值)之和最小一条路径,称为最短路径。 知道了...
  • title: ‘最短路径:迪杰斯特拉算法实现’ date: 2019-09-03 19:42:02 tags: python,数据结构 categories: 计算机理论 最短路径 dijkstra算法 算法原理 在看迪杰斯特拉算法之前,可以先回顾下BFS算法过程。BFS...
  • 迪杰斯特拉算法用来解决在有向有权图中某一个点到任意一点的最短路径问题。 注意:只能用来解决权为非零情况,不能够解决权为负数情况 思想:我是一个搬运工 思想就不讲了,主要是代码: def dijstra(adjacent,...
  • 迪杰斯特拉算法求解,迪杰斯特拉算法书上的描述如下: 对于图G=(V,{E}),将图中的顶点归为两组: 第一组S:已求出的最短路径的终点集合(开始为{v0}) 第二组:V-S尚未求出的最短路径的顶点...
  • 求图单源最短路径迪杰斯特拉算法 1.题意 给出一个有向图边信息,以及边权信息。让你求出从指定点作为源点到其它点的最短路径。 2.分析 使用迪杰斯特拉算法。算法主要思想如下: 基本思想: 对图G(V,E)设置...
  • Content1. 什么是最短路径2. 迪杰斯特拉算法【O(n^2^)】3....该算法用到了贪心的思想,设 v0为源点,S 为已求得的最短路径的终点集合; 则下一条最短路径。( 设其终点为 v)或者是弧 < v0, v>, 或者是中间
  • 最短路径迪杰斯特拉)Dijkstra算法的理解 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止...
  • 在常用的单源点最短路径算法中,迪杰斯特拉算法是最为常用的一种,是一种按照路径长度递增的次序产生最短路径的算法。 可将迪杰斯特拉算法描述如下: 在本题中,读入一个有向图的带权邻接矩阵(即数组表示),...
  • 最短路径7.5.1 弧上权值为非负情形单源点最短路径问题弧上权值为非负情形单源点最短路径概念迪杰斯特拉算法实现过程算法思路 7.5.1 弧上权值为非负情形单源点最短路径问题 弧上权值为非负情形单源点最短路径...
  • 迪杰斯特拉算法用于求解最短路径问题,具体地说是求解一个有向图(或无向图,无向图是有向图一个特例)中一个点到其余各点的最短路径,既然是求解最短路径问题,自然这里所描述边都是具有权值。...
  • # 简明理解最短路径之迪杰斯特拉算法 # 用途 迪杰斯特拉算法,用来寻找一个带权有向图中的某一顶点v0(源顶点)分别到...用集合V代表图中所有顶点的集合,集合S代表已经找出了最短路径的顶点,那么集合S-V则为尚未
  • 最短路径——迪杰斯特拉算法

    千次阅读 2016-08-23 20:29:58
    好久没有更新过算法博客了,这篇博客主要介绍我们算法中很著名一个问题——最短路径问题及解决最短路径问题经典算法之一迪杰斯特拉算法最短路径问题 最短路径问题是图论研究中一个经典算法问题, 旨在...
  • 上次在最短路径迪杰斯特拉算法模板(一)中提到上个模板只能适用于最短路径唯一情况。有时算法竞赛题目会碰到两条及两条以上可以到达最短距离路径,题目就会给出一个第二标尺(第一标尺是距离),要求在所有最短...
  • 迪杰斯特拉算法是关于图的最短路径的一种算法,按照***最短路径长度从小到大的顺序***找到每个点的最短路径。 主要思想是这样的:假设有一点集Q(其中包含的点都是找到最短路径的点),图中部分点都在该点集中。A...
  • 的最短路径迪杰斯特拉算法和弗洛伊德算法

    万次阅读 多人点赞 2018-06-05 20:03:51
      Dijkstra(迪杰斯特拉)算法是典型单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法的时间复杂度为O(N^2)。例如求下图中...
  • 最短路径迪杰斯特拉算法

    千次阅读 2017-09-12 09:04:22
    本文将讲解图中最短路径的求解算法之迪杰斯特拉算法及其Java实现。
  • 最短路径: (1) 在网图中,指两顶点之间经历边上权值之...迪杰斯特拉(Dijkstra)算法 :按路径长度递增次序产生最短路径 求从A到各顶点最短距离: 初始:S = < A > 第一步:S = <A, B> A->B: (A,
  • 1. 迪杰斯特拉算法的思想:是从起点开始,根据边权值信息逐步推出到各个顶点最小值,然后利用推导出来最小权值顶点不断迭代更新到顶点最小路径; 2. 结合上图来看下推导过程: a. 默认v0到v1、v2...v8各个...
  • 在常用的单源点最短路径算法中,迪杰斯特拉算法是最为常用的一种,是一种按照路径长度递增的次序产生最短路径的算法。 单源点的最短路径问题:给定带权有向图G和源点v,求从v到G中其余各顶点的最短路径。 我们用一...
  • 对网图和非网图,最短路径含义的不同的。...若源点为v0,终点为v8,此算法不是一下子就求出了v0到v8的最短路径,而是一步步求出它们之间顶点的最短路径,过程中都是基于已经求出的最短路径的基础上,求得更远顶点的最

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,480
精华内容 992
关键字:

最短路径的迪杰斯特拉算法