首页 > 其他分享 >2642. 设计可以求最短路径的图类

2642. 设计可以求最短路径的图类

时间:2023-04-16 22:13:41浏览次数:54  
标签:图类 dist int ed 2642 路径 edges st vector

题目链接:2642. 设计可以求最短路径的图类

方法一:Dijkstra

解题思路

每次调用 \(shortestPath(st, ed)\) 时,就通过 \(Dijkstra\) 算法计算 \(st\) -> \(ed\) 的最短路。

代码

朴素写法

class Graph {
private:
    vector<vector<int>> adj;
    int e[110][110], n;
public:
    Graph(int n, vector<vector<int>>& edges){
        this->adj.resize(110);
        this->n = n;
        for (int i = 0; i < edges.size(); i ++ ) {
            int u = edges[i][0], v = edges[i][1], w = edges[i][2];
            adj[u].push_back(v);
            e[u][v] = w;
        }
    }
    
    void addEdge(vector<int> edge) {
        int u = edge[0], v = edge[1], w = edge[2];
        adj[u].push_back(v);
        e[u][v] = w;
    }
    
    int shortestPath(int st, int ed) {
        vector<int> isvisit(n), dist(n, INT_MAX);
        dist[st] = 0;
        while (1) {
            int tmp = INT_MAX, u = -1;
            for (int i = 0; i < n; i ++ ) { // 找剩余节点中dist最小的节点,加入集合,即st到当前节点的最短路已找到
                if (!isvisit[i] && dist[i] < tmp) {
                    tmp = dist[i];
                    u = i;
                }
            }
            if (u == -1) return -1; // 剩余节点无法到达
            if (u == ed) return tmp; // 已经找到st->ed的最短路
            isvisit[u] = 1;
            for (auto &v : adj[u]) { // 当前节点加入集合后,更新其邻接点的最短路大小
                if (!isvisit[v] && dist[u] + e[u][v] < dist[v]) {
                    dist[v] = dist[u] + e[u][v];
                }
            }
        }
    }
};

堆优化寻找剩余节点中 \(dist\) 最小节点的过程

class Graph {
private:
    vector<vector<int>> adj;
    int e[110][110], n;
public:
    Graph(int n, vector<vector<int>>& edges){
        this->adj.resize(110);
        this->n = n;
        for (int i = 0; i < edges.size(); i ++ ) {
            int u = edges[i][0], v = edges[i][1], w = edges[i][2];
            adj[u].push_back(v);
            e[u][v] = w;
        }
    }
    
    void addEdge(vector<int> edge) {
        int u = edge[0], v = edge[1], w = edge[2];
        adj[u].push_back(v);
        e[u][v] = w;
    }
    
    int shortestPath(int st, int ed) {
        vector<int> isvisit(n), dist(n, INT_MAX);
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q; // 堆优化
        dist[st] = 0;
        q.push({dist[st], st});
        while (1) {
            int tmp = INT_MAX, u = -1;
            if (!q.empty()) { // 找剩余节点中dist最小的节点,加入集合,即st到当前节点的最短路已找到
                auto front = q.top();
                q.pop();
                tmp = front.first;
                u = front.second;
            }
            if (u == -1) return -1;
            if (u == ed) return tmp;
            isvisit[u] = 1;
            for (auto &v : adj[u]) {
                if (!isvisit[v] && dist[u] + e[u][v] < dist[v]) {
                    dist[v] = dist[u] + e[u][v];
                    q.push({dist[v], v});
                }
            }
        }
    }
};

复杂度分析

时间复杂度:\(Graph():O(m),addEdge():O(1),shortestPath():O(n^2)\),堆优化:O(nlogn);
空间复杂度:\(shortestPath():O(n)\)。

方法二:Floyd

解题思路

每次调用 \(Graph()\) 时,就通过 \(Floyd\) 算法计算所有 \(x\) -> \(y\) 的最短路,然后在调用 \(addEdge()\) 时,判断是否需要更新相关的最短路。

class Graph {
private:
    vector<vector<int>> g;
    int n;
public:
    Graph(int n, vector<vector<int>>& edges) {
        // O(n^3)
        this->n = n;
        g = vector<vector<int>>(n, vector<int>(n, INT_MAX / 3));
        for (int i = 0; i < n; i ++ ) g[i][i] = 0;
        for (auto &e : edges)
            g[e[0]][e[1]] = e[2];
        for (int k = 0; k < n; k ++ ) 
            for (int i = 0; i < n; i ++ ) 
                for (int j = 0; j < n; j ++ ) 
                    g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
    }
    
    void addEdge(vector<int> e) {
        // O(n^2)
        int u = e[0], v = e[1], w = e[2];
        if (w >= g[u][v]) return ;
        g[u][v] = w;
        for (int i = 0; i < n; i ++ ) 
            for (int j = 0; j < n; j ++ ) 
                g[i][j] = min(g[i][j], g[i][u] + w + g[v][j]);
    }
    
    int shortestPath(int st, int ed) {
        // O(1)
        return g[st][ed] < INT_MAX / 3 ? g[st][ed] : -1;
    }
};

标签:图类,dist,int,ed,2642,路径,edges,st,vector
From: https://www.cnblogs.com/lxycoding/p/17324226.html

相关文章

  • coc-settings中设置自定义头文件路径
    具体方案例如{"suggest.noselect":true,"languageserver":{"ccls":{"command":"ccls","filetypes":["cc","c","cpp","cuda"]......
  • 如何配置.h头文件include“”相对路径
    编译工程时,找的是当前main.c文件下的.h文件,如果当前路径下没有就会报错,当前路径用.\表示,上一级目录用..\表示。如果你的main.h文件在main.c的上一级目录中Include文件夹内,这样来表示:#include“..\Include\main.h”总结:编译工程时找的是当前程序文件目录下的.h文件。—————......
  • C#-获取当前用的的桌面路径
    stringdir=Environment.GetFolderPath(Environment.SpecialFolder.CommonPictures);//图片stringdir=Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);//桌面stringdir=Environment.GetFolderPath(Environment.SpecialFolder.CommonDo......
  • HDU 1116 && POJ 1386 Play on Words(欧拉路径)
    按字母来建边,每个单词的首字母和尾字母加边。先判断是否连通,然后判断每个字母的入度和出度不能出现差的绝对值大于2,然后入度和出度差的绝对值为1的不能超过两个。就可以形成欧拉路径代码如下:#include<iostream>#include<string.h>#include<math.h>#include<queue>#include......
  • Node.js文件路径:Path模块
    path模块是nodejs的内置模块,便于我们去获取、操作文件路径记录一些注意事项:文件的绝对位置cjsconsole.log(__filename)mjsmjs中,不能使用__filename和__dirnameconsole.log(import.meta.url)文件所处的目录cjsconsole.log(__dirname)mjsimport{dirname}from"path......
  • leetcode:路径总和 III
    问题描述给定一个二叉树的根节点root ,和一个整数targetSum,求该二叉树里节点值之和等于targetSum的路径的数目。路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。示例1输入:root=[10,5,-3,3,2,null,11,3,-2,null,1],ta......
  • 打开OneNote时,显示指定路径不存在
    提示错误:当Win桌面软件显示指定路径不存在时,可能有以下几个原因:路径输入错误:检查一下输入的路径是否正确,是否存在拼写错误或者路径分隔符(如反斜杠“\”)是否正确。路径被删除或移动:路径指向的文件或文件夹可能已被删除或移动到了其他位置。在这种情况下,你可以尝试搜索文件名或文件......
  • 基于蚁群优化算法的三维路径规划算法matlab仿真
    1.算法仿真效果matlab2022a仿真结果如下:2.算法涉及理论知识概要蚁群算法是受到对真实蚂蚁群觅食行为研究的启发而提出。生物学研究表明:一群相互协作的蚂蚁能够找到食物和巢穴之间的最短路径,而单只蚂蚁则不能。生物学家经过大量细致观察研究发现,蚂蚁个体之间的行为是相互作用......
  • springboot 中的 classpath 指的是什么路径?
    classpath其本质其实是指项目打包后的classes下的路径,一般用来指代“src/main/resources”下的资源路径。通常会在各种配置文件中使用【classpath】关键字,例如:yml配置文件:WebMvcConfigurer配置类:......
  • JavaWeb中Servlet、web应用和web站点的路径细节("/"究竟代表着什么)
    JavaWeb中Servlet、web应用和web站点的路径细节("/"究竟代表着什么) 1开门见山新建一个tomcatweb项目,配置tomcat的虚拟目录,取默认值(/项目名_war_exploded)那么如果你的tomcat的默认站点(即http://localhost:8080)没有更改的话,这个项目的两个重要的根目录就出来了web站点根目......