代码随想录算法训练营Day-58 图论08 | 拓扑排序精讲、dijkstra(朴素版)精讲

拓扑排序精讲

一堆软件有前置依赖关系,找到一条可行的安装顺序

思路:

1.找到入度为0的节点;2.将入度为0的节点加入结果集,然后删除该节点。重复以上过程即可

细节:

入度用一个数组记录,记录每个节点的入度;

**如何删除节点?**只需把节点所连接的子节点的入度都减一;

如何找到节点所连接的所有子节点? 定义一个键值对,键是父节点,值是所连接的节点组成的数组;

**如何找到入度为0的节点?**不需要每次都遍历,只需要在遇到入度为0的节点时就加入队列,然后只要队列不空,就循环执行"将队头取出,加入结果集,删除队头,删除节点,再判断节点连接的子节点是否入度为0,如果是就也加入"。

cpp 复制代码
#include<iostream>
using namespace std;
#include<vector>
#include<queue>
#include<unordered_map>

int main(){
    int n,m,s,t;
    cin>>n>>m;
    vector<int> indegree(n,0);
    vector<int> result;
    unordered_map<int,vector<int>> umap;
    queue<int> que;

    while(m--){
        cin>>s>>t;
        indegree[t]++;
        umap[s].push_back(t);
    }

    for(int i=0;i<n;i++){
        if(indegree[i]==0){
            que.push(i);
        }
    }

    while(!que.empty()){
        int cur = que.front(); que.pop();
        result.push_back(cur);
        vector<int> notes = umap[cur];
        if(notes.size()){
            for(int i=0;i<notes.size();i++){
                indegree[notes[i]]--;
                if(indegree[notes[i]]==0) que.push(notes[i]);
            }
        } 
    }
    if(n == result.size()){
        for(int i=0;i<n-1;i++){
            cout<<result[i]<<" ";
        }
        cout<<result[n-1]<<endl;
    }else{
        cout<<-1<<endl;
    }

}

dijkstra(朴素版)精讲

本题是在有向有权图中,找到起点到终点的最短路径距离

思路:和prim算法高度类似

1.找到距离起点最近的没被访问过的节点(搜索minDist中的没被访问过的节点的最小值)

2.将该节点标记为访问过(将visitedcur置为true)

3.更新所有没被访问过的节点到起点的最短距离(遍历节点,判断节点是否访问过 && 是否和当前节点连接 && 是否到起点的距离小于之前记录的距离(因为如果途径新的当前节点可能会获得更短的距离))

cpp 复制代码
#include<iostream>
#include<vector>
#include <climits>
using namespace std;
int main(){
    int n,m,s,t,val;
    cin>>n>>m;
    vector<vector<int>> graph(n+1,vector<int>(n+1,INT_MAX));
    while(m--){
        cin>>s>>t>>val;
        graph[s][t]= val;
    }

    vector<int> minDist(n+1, INT_MAX);
    vector<bool> visited(n+1, false);
    int start = 1; 
    int end = n;
    minDist[1] = 0;
    for(int i=1;i<=n;i++){
        int cur = 1;
        int minval = INT_MAX;
        for(int j=1;j<=n;j++){
            if(visited[j]==false && minval>minDist[j]){
                minval = minDist[j];
                cur = j;
            }
        }

        visited[cur] = true;
        for(int k=1;k<=n;k++){
            if(visited[k] == false &&graph[cur][k]!=INT_MAX && graph[cur][k]+minDist[cur]<minDist[k]){
                minDist[k] = graph[cur][k]+minDist[cur];
            }
        }
    }
    if(minDist[n]==INT_MAX){
        cout<<-1<<endl;
        return 0;
    }
    cout<<minDist[n]<<endl;
}

相关推荐
王维同学1 天前
Winsock 协议与名称空间 Provider 目录
网络·c++·windows·安全
拳里剑气1 天前
C++算法:BFS解决FloodFill算法
c++·算法·bfs·宽度优先
爱写代码的小朋友1 天前
从零开始学 Win32 API:C++ 窗口编程实战(VS Code + MinGW-w64 命令行详解)
开发语言·c++
小小晓.1 天前
C++:语句和作用域
开发语言·c++
fqbqrr1 天前
2607C++,soui,xplayer视频播放器
c++·soui
wanderist.1 天前
Lambda表达式在算法竞赛中的应用
java·开发语言·算法
zh路西法1 天前
【10天速通ROS2-PX4无人机】(四) 关掉GPS和气压计,纯激光定位还能飞吗
c++·无人机·px4·ros2·卡尔曼滤波·fastlio2
稚南城才子,乌衣巷风流1 天前
支配树(Dominator Tree)详解:概念、算法与应用
算法
稚南城才子,乌衣巷风流1 天前
动态开点:原理、实现与应用场景
数据结构·算法