Dijkstra(邻接矩阵实现)

本文深入讲解了使用邻接矩阵表示的有向图的Dijkstra算法,详细解释了如何寻找单源最短路径,包括初始化图、核心算法实现及具体步骤说明。

Dijkstra使用邻接矩阵存储图对比于邻接表,会占据大量内存,但通常此类题目不会卡内存。

/**
 * 邻接矩阵表示的有向图的Dijkstra(单源最短路径)算法
 * 顶点节点编号默认范围为[0,N-1]!即N个顶点编号不允许取到N
 */
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define Max 20000   //最大点编号
int Map[Max][Max];  //图的邻接矩阵表示
int flag[Max];      //顶点访问标记
int ans[Max];       //记录各点到起点距离
int S,E;            //起点终点
int N,M;            //节点数和边数
void Dijkstra()
{
    memset(flag,0,sizeof(flag));
    memset(ans,0x3f,sizeof(ans));
    ans[S]=0;
    while(true)
    {
        int v=-1;  //标记目前访问结点
        for(int u=0;u<N;u++)  //遍历所有顶点,找到当前 未访问过 且 离起点源最近 的节点
        {
            if(!flag[u]&&(v==-1||ans[u]<ans[v]))  
                v=u;
        }
        if(v==-1) return;  //所有顶点都访问完成,则完成最短路径计算
        flag[v]=1;  //访问标记
        for(int i=0;i<N;i++)  //计算更新目前所有访问过顶点的最短路径,即比较 目前访问节点带来的路径 和 之前记录的最短路径
            ans[i]=min(ans[i],ans[v]+Map[v][i]);
    }
}
int main()
{
    cin>>N>>M;                       //输入顶点数和边数
    memset(Map,0x3f,sizeof(Map));    //初始化图
    for(int i=1;i<=M;i++)            //输入每条边
    {
        int u,v,cost;
        cin>>u>>v>>cost;
        if(cost<Map[u][v])   //考虑题目可能同边不同值,只取最短边
            Map[u][v]=cost;  //无向图的话再令Map[v][u]=cost即可
    }
    cin>>S>>E;       //输入起点和终点,Dijkstra求的是单源最短路径
    Dijkstra();
    if(ans[E]==INF)  //不能到达
        cout<<"-1"<<endl;
    else
        cout<<ans[E]<<endl;   
}

 

Dijkstra算法是一种用于解决单源最短路径问题的经典贪心算法,适用于带权有向图或无向图,其中所有边的权重必须为非负数。该算法通过不断扩展最短路径树来找到从起点到其他所有顶点的最短路径。 ### Dijkstra算法的核心思想 1. 从起点开始,逐步扩展到其他顶点,每次选择当前未处理的最短路径顶点。 2. 利用一个距离数组 `dist[]` 来记录从起点到各个顶点的最短路径估计值。 3. 使用一个布尔数组 `visited[]` 来标记顶点是否已经找到最短路径。 4. 对于每一个选中的顶点,更新其邻接顶点的最短路径估计值。 ### 数据结构定义 为了表示图,使用邻接矩阵作为存储结构[^2]。邻接矩阵是一个二维数组,其中 `graph[i][j]` 表示从顶点 `i` 到顶点 `j` 的边的权重,如果不存在边,则值为 `INFINITY`(一个足够大的值表示不可达)。 ### C++实现Dijkstra算法 以下是基于邻接矩阵的C++实现: ```cpp #include <iostream> #include <climits> using namespace std; #define V 6 // 定义顶点数量 #define INFINITY INT_MAX // 用INT_MAX表示不可达的距离 // 打印最终结果 void printSolution(int dist[], int n) { cout << "Vertex Distance from Source" << endl; for (int i = 0; i < V; i++) cout << i << " \t\t" << dist[i] << endl; } // 查找距离数组中最小距离的顶点 int minDistance(int dist[], bool visited[]) { int min = INFINITY, min_index; for (int v = 0; v < V; v++) if (!visited[v] && dist[v] <= min) min = dist[v], min_index = v; return min_index; } // Dijkstra算法主体 void dijkstra(int graph[V][V], int src) { int dist[V]; // 最短距离数组 bool visited[V]; // 是否已经找到最短路径 // 初始化所有距离为无穷大,visited数组为false for (int i = 0; i < V; i++) dist[i] = INFINITY, visited[i] = false; dist[src] = 0; // 起始点到自己的距离为0 // 主循环,找到最短路径 for (int count = 0; count < V - 1; count++) { int u = minDistance(dist, visited); // 选择当前最短距离的顶点 visited[u] = true; // 标记该顶点已处理 // 更新邻接顶点的距离 for (int v = 0; v < V; v++) if (!visited[v] && graph[u][v] && dist[u] != INFINITY && dist[u] + graph[u][v] < dist[v]) dist[v] = dist[u] + graph[u][v]; } printSolution(dist, V); // 打印结果 } // 示例主函数 int main() { int graph[V][V] = { {0, 10, 0, 0, 0, 8}, {0, 0, 10, 0, 0, 0}, {0, 0, 0, 7, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 2, 0, 9}, {0, 0, 0, 0, 0, 0} }; dijkstra(graph, 0); // 从顶点0开始执行Dijkstra算法 return 0; } ``` ### 实现说明 1. **邻接矩阵初始化**:使用二维数组 `graph[V][V]` 存储图的边权信息,其中 `V` 是顶点数量。 2. **距离数组初始化**:`dist[]` 数组初始化为 `INFINITY`,表示初始时所有顶点的最短路径未知。 3. **循环处理**:每次循环选择当前未处理顶点中距离最小的顶点,然后更新其邻接顶点的距离。 4. **时间复杂度**:该实现的时间复杂度为 $O(V^2)$,其中 $V$ 是顶点数量,适用于顶点数量较小的图。 ### 注意事项 - 图中不能包含负权边,否则Dijkstra算法无法正确运行。 - 如果图的规模较大,建议使用邻接表和优先队列优化Dijkstra算法,以降低时间复杂度。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值