题解(去注释35行,新增堆优化版)
2025-08-06 14:19:53
发布于:上海
35阅读
0回复
0点赞
朴素版
#include<iostream>
using namespace std;
int dis[1010],n,m,s,mp[1010][1010],vis[1010];
//dis记录到一个点的最短距离,mp记录权值,vis记录是否被访问过
void dijkstra(){
for(int i=1;i<n;i++){
int u=0;
for(int j=1;j<=n;j++)
if(vis[j]==0 && dis[j]<dis[u])u=j;
//松弛
vis[u]=1;
//标记已访问
for(int j=1;j<=n;j++){
if(mp[u][j]){
int w=mp[u][j];
if(dis[j]>dis[u]+w)dis[j]=dis[u]+w;
}
}
//再松弛
}
}
int main(){
cin>>n>>m>>s;
for(int i=0;i<=n;i++)
dis[i]=2e9;
dis[s]=0;
//初始化dis数组,方便后面记录
for(int i=0;i<m;i++){
int u,v,w;
cin>>u>>v>>w;
int tmp=mp[u][v] ? mp[u][v] : 2e9;
mp[u][v]=min(tmp,w);
//确保权值最小
}
dijkstra();
//自定义函数
for(int i=1;i<=n;i++){
if(dis[i]!=2e9)cout<<dis[i]<<" ";
else cout<<-1<<" ";
}
//输出
return 0;
}
堆优化版
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
const int N=1e6+5;
const ll INF=2e9;
vector<pair<int,ll>>g[N];
bool vis[N];//记录是否来过
ll dis[N];//dis[i] 表示起点到i的最短路
void dijkstra(int s,int n){//起点s
for(int i=1;i<=n;i++)dis[i]=INF,vis[i]=0;
dis[s]=0;
//pair<ll,in> first代表距离 second代表点
priority_queue<pair<ll,int>,vector<pair<ll,int>>,greater<pair<ll,int>>>q;
q.push({0,s});
while(q.size()){
ll d=q.top().first;//起点到当前点的距离
int u=q.top().second;//当前的点
q.pop();
if(vis[u])continue;//当前点遍历过->跳过
vis[u]=1;
for(auto [v,w]:g[u]){// v first u->v 边权值
if(dis[v]>dis[u]+w){//当前起点到v的距离<当前起点u的距离+u到v的距离
dis[v]=dis[u]+w;
q.push({dis[v],v});
}
}
}
}
int main(){
int n,m,s;
cin>>n>>m>>s;
for(int i=0;i<m;i++){
int u,v,w;
cin>>u>>v>>w;
g[u].push_back({v,w});
}
dijkstra(s,n);
for(int i=1;i<=n;i++){
if(dis[i]==INF)cout<<"-1 ";//如果等于INF说明没有更新也就是不能到达
else cout<<dis[i]<<" ";//否则直接输出
}
return 0;
}
这里空空如也
有帮助,赞一个