代码随想录算法训练day64---图论系列8《拓扑排序&dijkstra(朴素版)》

代码随想录算法训练

---day64

文章目录

  • 代码随想录算法训练
  • 前言
  • [一、53. 117. 软件构建---拓扑排序](#一、53. 117. 软件构建—拓扑排序)
  • [二、47. 参加科学大会---dijkstra(朴素版)](#二、47. 参加科学大会---dijkstra(朴素版))
  • 总结

前言

今天是算法营的第64天,希望自己能够坚持下来!

今天继续图论part!今日任务:

● 拓扑排序

●dijkstra(朴素版)


一、53. 117. 软件构建---拓扑排序

卡码网题目链接
文章讲解

给出一个 有向图,把这个有向图转成线性的排序 就叫拓扑排序。

适合应用在例如B依赖A,C依赖B,要先有A才能有B,先有B才能有C的依赖关系找出先后顺序的问题。

实现拓扑排序的算法有两种:卡恩算法(BFS)和DFS,一般来说我们只需要掌握 BFS (广度优先搜索)就可以了,清晰易懂。

思路:

找 入度为 0 的节点,只有入度为0,它才是出发节点。

步骤:

1.找到入度为0 的节点,加入结果集

2.该节点指向的节点入度-1

代码如下:

cpp 复制代码
#include<iostream>
#include<vector>
#include<unordered_map>
#include<queue>
using namespace std;
 
int main() {
    int n, m, s, t;
    cin >> n >> m;
    vector<int> inDegree(n, 0); //记录每个文件的入度
     
    unordered_map<int, vector<int>> umap; //记录文件的依赖 first指向多个second文件
    vector<int> result; //记录结果
     
    while (m--) {
        //s->t 先有s才能有t
        cin >> s >> t;
        inDegree[t]++;
        umap[s].push_back(t); //记录s指向哪些文件
    }
     
    //因为会有不只1个文件入度为0,用队列存放入度为0的文件
    queue<int>que;
    for (int i = 0; i < n; i++) {
        if (inDegree[i] == 0) que.push(i);        
    }
     
    //循环从队列中取出文件处理
    //1.将入度为0的文件加入结果集,2.删掉入度为0的文件
    while (!que.empty()) {
        int cur = que.front();
        que.pop();
        result.push_back(cur);
         
        vector<int> files = umap[cur]; //获取该文件指向的文件
        for (int j = 0; j < files.size(); j++) {
            inDegree[files[j]]--; //cur指向的文件入度-1
            if(inDegree[files[j]] == 0) que.push(files[j]); //新的入度为0的文件加入到队列
        }
    }
     
    //打印结果
    if (result.size() == n) {
        for (int i = 0; i < n - 1; i++) cout << result[i] << " ";
        cout << result[n - 1]; //最后不包含空格,所以分开打印
    } else {
        cout << -1 << endl;
    }
     
    return 0;
}

二、47. 参加科学大会---dijkstra(朴素版)

卡码网题目链接
文章讲解

dijkstra算法:在有权图(权值非负数)中求从起点到其他节点的最短路径算法。

需要注意两点:

  • dijkstra 算法可以同时求 起点到所有节点的最短路径
  • 权值不能为负数

dijkstra和prim算法思路很像,只是dijkstra是求最短路径,minDist数组 用来记录 每一个节点距离源点的最小距离 ;而prim里的minDist数组是记录每个节点到生成树的最小距离

dijkstra三部曲:

第一步,选源点到哪个节点近且该节点未被访问过

第二步,该最近节点被标记访问过

第三步,更新非访问节点到源点的距离(即更新minDist数组)

为了更好理解,数组下标从1开始,对应节点1,到达节点n对应下标n。

代码如下:

cpp 复制代码
#include<iostream>
#include<vector>
#include<climits>
using namespace std;
 
int main() {
    int n, m, s, e, v;
    cin >> n >> m;
    vector<vector<int>> grid(n + 1, vector<int>(n + 1, INT_MAX));
     
    while (m--) {
        cin >> s >> e >> v;
        grid[s][e]= v;
    }
     
    int start = 1;
    int end = n;
     
    vector<int>minDist(n+1, INT_MAX); //记录从原点到达每个节点的最短路径
    vector<bool>visited(n+1, false);
     
    minDist[start] = 0;
     
     
     //遍历所有节点
    for (int i = 1; i <= n; i++) { 
        int minVal = INT_MAX;
        int cur = 1; //当前节点
         
        //遍历minDist,找出距离原点最近且未访问的节点
        for (int j = 1; j <= n; ++j) {
            if (!visited[j] && minDist[j] < minVal) {
                minVal = minDist[j];
                cur = j;
            }
        }
         
        //标记访问过的节点
        visited[cur] = true;
         
        //更新minDist,这里是判断原点到当前节点+当前节点到下一个节点的距离是否比原来的近
        for (int j = 1; j <= n; j++) {
            if (!visited[j] && grid[cur][j] != INT_MAX && minDist[cur] + grid[cur][j] < minDist[j]) {
                minDist[j] = minDist[cur] + grid[cur][j];
            }
        }
    }
     
    if (minDist[end] == INT_MAX) cout << -1 << endl; //不能到达终点
    else cout << minDist[end] << endl; //到达终点最短路径
     
    return 0;
}

总结

  • 拓扑排序 :

    1.unordered_map<int, vector> umap,存放每个节点指向多个节点

    2.一个vectorinDegrees记录每个节点的入度

    3.遍历inDegrees,用队列queue存放入度为0的节点

    4.遍历queue,将入度为0指向的节点入度-1,并将新的入度为0的节点加入到队列中。

  • dijkstra算法:

    1.vector<vector>grid存放节点间的权值, vectorminDist存放每个节点到源点的最小距离,vectorvisited记录已经被访问的节点

    2.遍历每个节点,遍历minDist,找到离源点最小距离且未访问过的节点

    3.标记成已访问的节点

    4.更新minDist数组

明天继续加油!

相关推荐
酉鬼女又兒4 分钟前
27. 移除元素
数据结构·算法·排序算法
划破黑暗的第一缕曙光8 分钟前
[C++]:1.C++基础
c++·c++基础
TracyCoder12314 分钟前
LeetCode Hot100(28/100)——104. 二叉树的最大深度
算法·leetcode
执着25924 分钟前
力扣hot100 - 101、对称二叉树
数据结构·算法·leetcode
多恩Stone26 分钟前
【3D-AICG 系列-1】Trellis v1 和 Trellis v2 的区别和改进
人工智能·pytorch·python·算法·3d·aigc
三月微暖寻春笋27 分钟前
【和春笋一起学C++】(五十九)派生类和基类之间的关系
c++·基类·派生类·关系
mit6.82432 分钟前
模运算|z函数 字符串匹配
算法
阿豪只会阿巴34 分钟前
【吃饭香系列】二周目|代码随想录算法训练营第七天|454.四数相加II |383. 赎金信 |15. 三数之和 |18. 四数之和
算法
小O的算法实验室37 分钟前
2025年COR SCI2区,考虑风场影响的无人机搜救覆盖路径规划精确界算法,深度解析+性能实测
算法·无人机·论文复现·智能算法·智能算法改进
xqqxqxxq39 分钟前
洛谷算法1-3 暴力枚举(NOIP经典真题解析)java(持续更新)
java·开发语言·算法