zoukankan      html  css  js  c++  java
  • dijkstra 两点的最短路径 单源 最短路径

     思路以dist数组 来扩充  路径的访问,不断的刷新dist数组

      设置一个顶点的集合s,并不断地扩充这个集合,一个顶点属于集合s当且仅当从源点到该点的路径已求出。开始时s中仅有源点,并且调整非s中点的最短路径长度,找当前最短路径点,将其加入到集合s,直到终点在s中。
    基本步骤:
    1、把所有结点分成两组:
          第一组:包括已经确定最短路径的结点;
          第二组:包括尚未确定最短路径的结点。
    2、开始时,第一组只包含起点,第二组包含剩余的点;
    3、用贪心的策略,按最短路径长度递增的顺序把第二组的结点加到第一组去,直到v0可达的所有结点都包含于第一组中。在这个过程中,不断更新最短路径,总保持从v0到第一组各结点的最短路径长度dist都不大于从v0到第二组任何结点的路径长度。
    4、每个结点对应一个距离值,第一组结点对应的距离就是v0到此结点的最短路径长度,第二组结点对应的距离值就是v0由第一组结点到此结点的最短路径长度。
    5、直到所有的顶点都扫描完毕(v0可达的所有结点都包含于第一组中),找到v0到其它各点的所有最短路径。

    如图:求0点到其他点的最短路径。

    (1)开始时,s1={v0},s2={v1,v2,v3,v4},v0到各点的最短路径是{0,10,&,30,100};
    (2)在还未进入s1的顶点之中,最短路径为v1,因此s1={v0,v1},由于v1到v2有路径,因此v0到各点的最短路径更新为{0,10,60,30,100};
    (3)在还未进入s1的顶点之中,最短路径为v3,因此s1={v0,v1,v3},由于v3到v2、v4有路径,因此v0到各点的最短路径更新为{0,10,50,30,90};
    (4)在还未进入s1的顶点之中,最短路径为v2,因此s1={v0,v1,v3,v2},由于v2到v4有路径,因此v0到各点的最短路径更新为{0,10,50,30,60};
    数据结构:
    (1)用一个二维数组a[i..j,i..j]来存储各点之间的距离,0x7fffffff表示无通路:

    (2)用数组dist[i..j]表示最短路径;
    (3)用集合s表示找到最短路径的结点。   

    <转  http://www.cnblogs.com/Soul-ice-ACM/articles/2140221.html >

    松弛原理

    #include<cstdio>
    #include<queue>
    #include<vector>
    #include<map>
    #include<string>
    #include<iostream>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define INF 0x7fffffff
    #define LL __int64
    
    const int maxn=105;
    int mpt[maxn][maxn];
    int vis[maxn];
    int m,n;
    int dist[maxn];//从起点到其他点的最短距离
    
    int dijkstra()
    {
        int start,end;
        start=1;end=n;
        for(int i=1;i<=n;i++)
            dist[i]=mpt[start][i];
        vis[1]=1;
        while(true)
        {
            //第一步
            //找出与起点集合相连的最短边
            int minx=INF;
            int v;
            for(int i=1;i<=n;i++)
            {
                if(dist[i]<minx&&vis[i]==0)
                {
                    minx=dist[i];
                    v=i;
                }
            }
            if(minx>=INF)break;//如果所有点都在起点集合内
            vis[v]=1;
            //松弛、更新DIST数组
            for(int i=1;i<=n;i++)
            {
                if(vis[i]==0&&dist[i]>dist[v]+mpt[v][i]&&dist[v]<INF&&mpt[v][i]<INF)
                {
                    dist[i]=dist[v]+mpt[v][i];
                }
            }
        }
        return dist[end];
    }
    
    void init()
    {
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i==j)mpt[i][j]=0;
                else
                    mpt[i][j]=INF;
            }
        }
    }
    
    int main()
    {
    
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            if(n==0&&m==0)break;
            init();
            //建图
            for(int i=1;i<=m;i++)
            {
                int a,b,c;
                scanf("%d%d%d",&a,&b,&c);
                if(c<mpt[a][b])
                {
                    mpt[a][b]=c;
                    mpt[b][a]=c;
                }
            }
            printf("%d
    ",dijkstra());
        }
    
        return 0;
    }
  • 相关阅读:
    C#时间差
    centos8安装ffmpeg
    CentOS8同步时间
    安装Supervisor
    ajax 传递 token
    .net core 3.1 中 的跨域设置
    jaeger 本地编译
    Kubernates 环境搭建
    linux : find
    Linux: 文件分割和合并
  • 原文地址:https://www.cnblogs.com/locojyw/p/3734376.html
Copyright © 2011-2022 走看看