代码随想录Day59|dijkstra(堆优化版)精讲、Bellman_ford 算法精讲
目录
- dijkstra(堆优化版)精讲
- 解题思路
- 解法
- Bellman_ford 算法精讲
- 解题思路
- 解法
- 今日总结
dijkstra(堆优化版)精讲
题目链接:KamaCoder
文章讲解:代码随想录
视频讲解:bilibili
解题思路
使用堆进行优化的初衷是,对于稀疏图来说,用点的方式进行遍历的开销较大,如果能对边进行求解,时空开销都将减小。
实际上也是从起点出发,然后对起点所能到达的点进行距离修改,并将其加入堆中,由于是小顶堆,每次的堆顶都是当前从源点出发距离最小的点,并在在处理相应的点时才会对其进行访问标记,确保能够在处理该点之前得到源点到达该点的最小距离,因为标记过的点将不再更新距离。可以看到本质上还是和点处理方式相同,处理逻辑有了一点变化。
解法
#include <iostream>
#include <vector>
#include <list>
#include <queue>
#include <climits>using namespace std;class mycomparation{
public:bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs){return lhs.second > rhs.second;}
};struct Edge{int to, val;
} ;int main(){int n, m;cin >> n >> m;vector<list<Edge>> grid(n+1);for(int i=0; i<m; i++){int s, t, val;cin >> s >> t >> val;grid[s].push_back({t, val});}int start = 1;int end = n;vector<int> minDis(n+1, INT_MAX);vector<bool> visited(n+1, false);priority_queue<pair<int, int>, vector<pair<int, int>>, mycomparation> pq;pq.push({start, 0});minDis[start] = 0;while(!pq.empty()){pair<int, int> cur = pq.top();pq.pop();visited[cur.first] = true;for(Edge edge : grid[cur.first]){if(!visited[edge.to] && minDis[cur.first] + edge.val < minDis[edge.to]){minDis[edge.to] = minDis[cur.first] + edge.val;pq.push({edge.to, minDis[edge.to]});}}}if(minDis[end] == INT_MAX) cout << -1 << endl;else cout << minDis[end] << endl;return 0;}
- 时间复杂度:O(mlogm)O(mlogm)O(mlogm)
- 空间复杂度:O(n+m)O(n+m)O(n+m)
Bellman_ford 算法精讲
题目链接:KamaCoder
文章讲解:代码随想录
视频讲解:bilibili
解题思路
松弛是该算法的核心,从第一个点出发,每次都松弛所有的边,由于总共有n个点,那么进行n-1次松弛就能得到源点到达终点的最小开销。为什么n-1次就足够呢?首先,n-1次确保所有节点都能被松弛到,如果该点是从源点出发可到达的话;其次,想要到达终点,就必须走终点的入边,因此需要这些入边的出发点能够在n-1次松弛时已经知道从源点出发到达的最小距离。反观第一轮,源点到自身的距离最小,为0,那么第一轮松弛结束之后,源点出边能够到达的点的最小距离就确定下来了。更通俗的说即为,第一轮松弛之后,与源点 一条边 相连的点的最小距离被确定了下来,那么n-1轮之后就能定下来终点的最小距离。
解法
#include <iostream>
#include <vector>
#include <climits>using namespace std;int main(){int n, m;cin >> n >> m;vector<vector<int>> grid;for(int i=0; i<m; i++){int s, t, pri;cin >> s >> t >> pri;grid.push_back({s, t, pri});}int start = 1;int end = n;vector<int> minDis(n+1, INT_MAX);minDis[start] = 0;for(int i=0; i<n-1; i++){for(vector<int>& side : grid){int from = side[0];int to = side[1];int pri = side[2];if(minDis[from]!=INT_MAX && pri + minDis[from] < minDis[to]){minDis[to] = pri + minDis[from];}}}if(minDis[end]==INT_MAX) cout << "unconnected" << endl;else cout << minDis[end] << endl;return 0;
}
- 时间复杂度:O(nm)O(nm)O(nm)
- 空间复杂度:O(n)O(n)O(n)
今日总结
补卡中()
