LY的数据结构复习——最短路径问题(dijkstra算法)

采取不断访问邻接矩阵的方法不断更新最短路径的单源最短路径算法。

定义:

邻接矩阵G[n][n],存储两两之间的边以及权重

数组s[n],用来判定某个结点是否已经处理过

数组dist[n],用来保存源结点到各各结点的最短路径

假如有一个图

 邻接矩阵即为

G[7][7]=

[0,4,6,6,-1,-1,-1

-1,0,1,-1,7,-1,-1

-1,-1,0,-1,6,4,-1

-1,-1,2,0,-1,5,-1

-1,-1,-1,-1,0,-1,6

-1,-1,-1,-1,1,0,8

-1,-1,-1,-1,-1,-1,0]其中的负一表示无边,也可表示为正无穷

s[7]=[0,0,0,0,0,0,0]

dist[7]=[0,0,0,0,0,0,0]

首先将处理数组中的源点置1,表示要处理源点了即s[0]=1

然后我们查看G[0][n]=[0,4,6,6,-1,-1,-1]

那么我们就知道从源点开始能到达1、2、3号结点以及权重

接着我们更新dist,即dist=[0,4,6,6,-1,-1,-1],表示源点到这些点目前的最短路径

接下来我们选取dist中最小取值点的下标(可达的点),即1号点

我们将一号点加入其中,即s[1]=1

查看G[1][n] = [-1,0,1,-1,7,-1,-1]

我们知道1能到达1、2、4以及权重

接着我们更新dist,这时的更新值应该取min(dist[x],G[1][x]+dist[1])此步意义为要不之前就能到,要不经过1到,取最短的内条路径。

接着取dist中最小取值点下标,且该点未被s记录,然后以此类推……

拿一道学校的例题来复习,题目:

 这道题是高速路,显然是无向图,那么邻接矩阵必是对称的,代码:

#include <iostream>
#include <cmath>
#include <cstring>

using namespace std;

int Max = 65535;


int main()
{
    int n,c,s,t;
    cin>>n>>c>>s>>t;
    
    int *s1 = new int[n];                   //创建结点数组

    int **G = new int* [n];                 //创建邻接矩阵            
    for(int i = 0; i<n ; i++){
        G[i]=new int [n];
    }

    for(int i = 0;i<c;i++){                 //初始化邻接矩阵,权值最小的边保留
        int a,b,d;
        cin>>a>>b>>d; 
        if(G[a-1][b-1] && G[a-1][b-1]<d);    
        else{
             G[a-1][b-1]=d;
            G[b-1][a-1]=d;
       
        }
       
        
    }
    

    int *dist = new int [n];                //最短路径距离数组
   

    for(int i = 0;i<n;i++){                 //初始化结点数组
        s1[i] = 0;
    }


    for(int i = 0 ; i<n;i++ ){                  //对邻接矩阵中未赋值的点设置为距离正无穷
        for(int j = 0 ; j < n ;j++)
        {
            if(!G[i][j])
                G[i][j] = Max;
        }
    }

    s1[s-1]=1;                                //初始化节点位置
    
    for(int i = 0;i<n;i++){                 
        dist[i] = G[s-1][i];
    }

    for(int i = 0 ;i<n-1;i++)
    {
        int minpoint_index;                //最小值点下标
        int minpoint = 20000;                    
        for(int i = 0 ; i<n;i++)
        {
            if(!s1[i] && dist[i]<minpoint )
            {
                minpoint = dist[i];
                minpoint_index = i;
            }
        }

        s1[minpoint_index] = 1;
        for(int i = 0;i<n;i++){                 
        dist[i] = min(G[minpoint_index][i]+dist[minpoint_index],dist[i]);
        }
    }
    cout<<dist[t-1];
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值