Dijkstra - cpp

本文介绍了如何使用C++实现Dijkstra算法,通过广度优先搜索(BFS)、贪心策略及优先级队列,解决从起点到终点城市的最短路径问题。代码实例详细展示了从输入城市图到计算最短路径并返回最优路径代价的过程。
摘要由CSDN通过智能技术生成

Dijkstra【cpp模板】

方法一:bfs + 贪心 + 优先级队列

代码:

#include <iostream>
#include <vector>
#include <queue>
#include <string>
using namespace std;

// graph:有权图
// start:起点城市
// end:终点城市
// n:城市数目
// pair<int, int>:first -> cost, second -> city
// path:记录最优路径【需要进一步处理】
int dijkstra(const vector<vector<pair<int, int>>> graph, int start, int end, int n, vector<int>& path) {
    vector<bool> isVisit(n, false); // 记录是否经过这个城市
    vector<int> best(n, INT_MAX);   // 记录最优cost

    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq; // 按cost从小到大取下一个要遍历的城市 // 贪心
    pq.push({0, start});    // 起点cost为0
    
    // bfs
    while (!pq.empty()) {
        auto cur = pq.top(); pq.pop();
        int city = cur.second;  // 当前遍历的城市
        int cost = cur.first;   // 到city目前耗费的cost

        // 如果当前城市是终点城市了,那直接return
        if (city == end) {
            return cost;
        }

        // 如果当前城市已经经过了,那进行下一轮循环
        if (isVisit[city]) {
            continue;
        }
        // 能到这步说明当前城市没经过,那么就在这次设置为true
        isVisit[city] = true;

        // 对于当前城市所连通的每个城市
        for (auto& next : graph[city]) {
            int nextCity = next.second;         // 下一个城市
            int nextCost = cost + next.first;   // 到达下一个城市的总cost

            // 如果下个城市已经经过了,或者如果这一步到达下个城市的总cost要比最优cost大,那么就跳过
            if (isVisit[nextCity] || best[nextCity] <= nextCost) {
                continue;
            }
            pq.push({nextCost, nextCity});
            best[nextCity] = nextCost;

            path[nextCity] = city;  // 从后往前,记录上一个城市
        }
    }
    return -1;  // 说明没连通
}

vector<vector<pair<int, int>>> getGraph(int n) {
    vector<vector<pair<int, int>>> graph(n, vector<pair<int, int>>());
    for (int i = 0; i < n; i++) {
        int city;
        cout << "城市: ";
        cin >> city;
        cout << "邻接: ";
        int cost, nextCity;
        while (cin >> cost >> nextCity) {
            graph[city].push_back({cost, nextCity});
            if (getchar() == '\n') {
                break;
            }
        }
    }
    return graph;
}

string getPath(vector<int>& path, int end) {
    string minPath;
    int preIdx = path[end];
    string ed = to_string(end);
    minPath += ed;
    while (preIdx != -1) {
        string city = to_string(preIdx);
        minPath += (">-" + city);
        preIdx = path[preIdx];
    }
    reverse(minPath.begin(), minPath.end());
    return minPath;
}

int main() {

    // int n = 7;
    cout << "城市数目: ";
    int n;
    cin >> n;
    vector<vector<pair<int, int>>> graph = getGraph(n);

    // graph.push_back({{12, 1}, {16, 5}, {14, 6}});
    // graph.push_back({{12, 0}, {10, 2}, {7, 5}});
    // graph.push_back({{10, 1}, {3, 3}, {5, 4}, {6, 5}});
    // graph.push_back({{3, 2}, {4, 4}});
    // graph.push_back({{5, 2}, {4, 3}, {2, 5}, {8, 6}});
    // graph.push_back({{16, 0}, {7, 1}, {6, 2}, {2, 4}, {9, 6}});
    // graph.push_back({{14, 0}, {8, 4}, {9, 5}});

    int start;
    int end;
    cout << "起点城市: ";
    cin >> start;
    cout << "终点城市: ";
    cin >> end;

    vector<int> path(n, -1);

    int res = dijkstra(graph, start, end, n, path);
    cout << "最优路径的代价: " << res << endl;

    string minPath = getPath(path, end);
    cout << "最优路径: " << minPath << endl;

    return 0;
}

参考资料

用例参考

核心代码参考

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Dijkstra最短路径算法是一种常用的图论算法,用于求解带权有向图中的最短路径。它的基本思想是从起点开始,逐步扩展到所有节点,每次选择当前距离起点最近的节点进行扩展,直到到达终点或者所有节点都被扩展完毕。在实现上,可以使用优先队列来维护当前距离起点最近的节点,以提高算法效率。C++是一种常用的编程语言,可以用来实现Dijkstra算法。 ### 回答2: Dijkstra算法是一种经典的求解最短路径问题(Single-Source Shortest Path)的算法,本质上是利用贪心策略编写的。它能够求出在给定的加权有向图中,从一个源节点到其他所有节点的最短路径,并且将这些最短路径编码成一个距离数组。 Dijkstra算法的基本思想是:从任意一个顶点出发,遍历整张图,逐步扩大已在树上的节点集合,同时不断更新节点的最短路径的距离值。 具体实现中,首先需要将所有节点的距离值初始化为"无穷大"(代表不可到达),起点的距离值设为0。接着,根据起点到所有相邻节点的距离,更新这些相邻节点的距离值。然后在所有未被确定的节点中,选择距离最小的那个节点,并且将它确定为当前节点,并更新其相邻节点的距离值。依次进行下去,直到到达目标节点,或者所有节点都被确定为止。 如果我们采用邻接矩阵作为图的存储结构,那么Dijkstra算法的时间复杂度是O(n^2),其中n是节点的数量。另外,还有一些优化措施,比如使用堆、二叉堆或斐波那契堆等数据结构,可以降低时间复杂度到O(nlogn)。 下面是Dijkstra算法C++实现代码: ```c++ #include <limits.h> #include <iostream> #include <vector> using namespace std; int minDistance(int dist[], bool sptSet[], int V) { int min = INT_MAX, min_index; for (int v = 0; v < V; v++) if (sptSet[v] == false && dist[v] <= min) min = dist[v], min_index = v; return min_index; } void printSolution(int dist[], int V) { cout << "Vertex Dist from source\n"; for (int i = 0; i < V; i++) cout << i << " - " << dist[i] << endl; } void dijkstra(vector<vector<int> > graph, int src) { int V = graph.size(); int dist[V]; bool sptSet[V]; for (int i = 0; i < V; i++) dist[i] = INT_MAX, sptSet[i] = false; dist[src] = 0; for (int count = 0; count < V - 1; count++) { int u = minDistance(dist, sptSet, V); sptSet[u] = true; for (int v = 0; v < V; v++) if (!sptSet[v] && graph[u][v] && dist[u] != INT_MAX && dist[u] + graph[u][v] < dist[v]) dist[v] = dist[u] + graph[u][v]; } printSolution(dist, V); } int main() { vector<vector<int> > graph = {{0, 4, 0, 0, 0, 0, 0, 8, 0}, {4, 0, 8, 0, 0, 0, 0, 11, 0}, {0, 8, 0, 7, 0, 4, 0, 0, 2}, {0, 0, 7, 0, 9, 14, 0, 0, 0}, {0, 0, 0, 9, 0, 10, 0, 0, 0}, {0, 0, 4, 0, 10, 0, 2, 0, 0}, {0, 0, 0, 14, 0, 2, 0, 1, 6}, {8, 11, 0, 0, 0, 0, 1, 0, 7}, {0, 0, 2, 0, 0, 0, 6, 7, 0}}; dijkstra(graph, 0); return 0; } ``` 上述代码中,我们用邻接矩阵存储了一个包含9个节点的测试图,并以节点0作为起始节点调用了dijkstra函数。在dijkstra函数中,我们首先初始化了dist和sptSet两个数组,接着进行了V-1次循环,每次找出当前距离起点最近但还未被访问过的节点,并将其加入sptSet数组。然后再以该节点为中心,更新当前最短距离,直到所有节点都被访问。 最后,我们将dist数组中存储的距离结果输出。该测试图的最短路由节点0->7->6->5->4->3->2->1->8(距离为14)。 ### 回答3: Dijkstra最短路径算法是一种经典的单源最短路径算法,采用贪心策略,找出从源节点到其它节点的最短路径,可用于在图中寻找任意两点之间的最短路径。 算法过程大概可以描述为以下几步: 1.初始化:选择最近的源节点,将其到每个节点的距离初始化为无穷大,将其到自身的距离初始化为0。 2.开始循环:从距离源节点最近的节点开始(初始为源节点),遍历该节点的所有邻居节点,更新其距离表(到源节点的距离)。 3.选择下一个节点:在距离表中找到距离源节点最近的未到达节点作为下一个节点进行遍历。 4.判断是否结束:如果当前节点的距离表已经更新过,且所有未到达的节点距离均为无穷大,则终止算法。如果还有未到达的节点,则将当前节点作为下一个起始节点,回到步骤2。 在实现Dijkstra算法时,需要使用优先队列来存储每个节点到源节点的距离,优先队列会根据距离表中的距离进行排序,从小到大取出最小值,可以将时间复杂度优化到O(E*logV)。 下面给出一份简单的基于C++Dijkstra最短路径算法实现: ```cpp #include <iostream> #include <vector> #include <queue> #define INF 0x3f3f3f3f using namespace std; typedef pair<int, int> P; vector<pair<int,int> > graph[100000]; int dist[100000]; void dijkstra(int start){ priority_queue<P, vector<P>, greater<P> > pq; pq.push(make_pair(0, start)); dist[start] = 0; while(!pq.empty()){ P p = pq.top(); pq.pop(); int node = p.second; if(dist[node] < p.first) continue; for(int i=0; i<graph[node].size(); i++){ int adjNode = graph[node][i].first; int adjDist = graph[node][i].second; if(dist[adjNode] > dist[node] + adjDist){ dist[adjNode] = dist[node] + adjDist; pq.push(make_pair(dist[adjNode], adjNode)); } } } } int main(){ int n, m, start; cin >> n >> m >> start; for(int i=0; i<m; i++){ int u, v, w; cin >> u >> v >> w; graph[u].push_back(make_pair(v, w)); } fill(dist, dist+n+1, INF); dijkstra(start); for(int i=1; i<=n; i++){ if(dist[i] == INF) cout << "INF" << endl; else cout << dist[i] << endl; } return 0; } ``` 其中,graph数组存储了所有节点之间的连通关系,dist数组存储了每个节点到起始节点的距离。算法的核心实现在dijkstra函数中,实现了前面所述的4个步骤。程序从标准输入读入图的信息,处理后输出每个节点到起始节点的距离(如果不可达,则输出INF)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值