dijkstra(堆优化版)精讲
文章讲解:代码随想录
题目链接:47. 参加科学大会(第六期模拟笔试)
operator()
是 函数调用运算符重载(Function Call Operator Overload),它让一个对象可以像函数一样被调用。
std::priority_queue<T, Container, Compare>
中,三个模板参数的含义如下 :
默认是大顶堆
T:元素类型
Container:底层容器类型
Compare:比较器
朴素迪杰斯特拉算法:
1.选取距离源节点并且未访过的节点
2.标记选取节点为已访问
3.更新权重
现在改为用邻接链表去存储图
list是双向链表
不支持随机访问
cpp
#include <iostream>
#include <vector>
#include <queue>
#include <list>
#include <climits>
//用来方便定义邻接链表
using namespace std;
struct Edge{
int to,val;
Edge(int _to,int _val):to(_to),val(_val){}
};
struct cmp{
bool operator()(pair<int,int>a,pair<int,int>b){
return a.second>b.second;
}
};
int main(){
int n,m;
cin>>n>>m;
vector<list<Edge>>grid(n+1);//邻接链表
for(int i=0;i<m;i++){
int s,e,v;
cin>>s>>e>>v;
grid[s].push_back(Edge(e,v));
}
int start=1;
int end=n;
vector<int>minDist(n+1,INT_MAX);
vector<bool>isVisited(n+1,false);
//优先队列 存储节点及节点到源点的距离
priority_queue<pair<int,int>,vector<pair<int,int>>,cmp>pq;
minDist[start]=0;
pq.push({start,0});
while(!pq.empty()){
//取最近点
auto cur=pq.top();
pq.pop();
if(isVisited[cur.first])continue;
//标记为已读
isVisited[cur.first]=true;
//更新minDist数组
list<Edge> edges=grid[cur.first];
for(auto it=edges.begin();it!=edges.end();it++){
if(!isVisited[it->to]&&minDist[cur.first]+it->val<minDist[it->to]){
minDist[it->to]=minDist[cur.first]+it->val;
pq.push({it->to,minDist[it->to]});
}
}
}
if(minDist[end]==INT_MAX) cout<<-1;
else cout<<minDist[end];
}
Bellman_ford
题目链接: 94. 城市间货物运输 I
文章讲解: 代码随想录
带有负权值的单源最短路径
核心思想:
对所有边进行n-1次松弛操作
cpp
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
vector<vector<int>>grid;
while(m--){
int s,t,v;
cin>>s>>t>>v;
grid.push_back({s,t,v});
}
vector<int>minDist(n+1,INT_MAX);
minDist[1]=0;
for(int i=1;i<n;i++){
for(int j=0;j<grid.size();j++){
int s=grid[j][0];
int t=grid[j][1];
int val=grid[j][2];
if(minDist[s]==INT_MAX)continue;
minDist[t]=min(minDist[s]+val,minDist[t]);
}
}
if(minDist[n]!=INT_MAX){cout<<minDist[n];}
else cout<<"unconnected";
}