解题思路
Dijkstra算法,基于贪心思想,适用于边的权值非负
算法流程:
1.初始化dis[s]=0,其他节点值为无穷大
2.找出一个未标记的,dis[x]最小的节点x,标记x
3.更新x的所有出边
4.重复2~3,直到所有点被标记
邻接矩阵写法
#include <bits/stdc++.h> using namespace std; const int N=1010; int a[N][N]; int dis[N]; int vis[N]; int n,m,s,t; int x,y,v; void dij(int s) { dis[s]=0; for(int i=1;i<n;i++) { int x=0; int y; for(int j=1;j<=n;j++) { if(!vis[j]&&(x==0||dis[j]<dis[x])) { x=j; } } vis[x]=1; for(int j=1;j<=n;j++) { dis[j]=min(dis[j],dis[x]+a[x][j]); } } } int main() { memset(a,0x3f,sizeof(a)); memset(dis,0x3f,sizeof(dis)); cin>>n>>m>>s>>t; for(int i=1;i<=n;i++) a[i][i]=0; for(int i=1;i<=m;i++) { cin>>x>>y>>v; a[x][y]=min(v,a[x][y]); a[y][x]=min(v,a[y][x]); } dij(s); if(dis[t]>=0x3f3f3f3f) cout<<-1<<endl; else cout<<dis[t]<<endl; return 0; }
链式前向星写法
#include <bits/stdc++.h> using namespace std; typedef pair<int,int> pii; const int N=1010; const int M=20010; int head[N],e[M],ne[M],w[M]; int dis[N]; bool vis[N]; int tot; int n,m,s,t; int x,y,v; void add(int x,int y,int z) { e[++tot]=y; w[tot]=z; ne[tot]=head[x]; head[x]=tot; } void dij(int s) { priority_queue<pii> p; dis[s]=0; p.push({0,s}); while(p.size()) { int x=p.top().second; p.pop(); if(vis[x]) continue; vis[x]=1; for(int i=head[x];i;i=ne[i]) { int y=e[i]; int z=w[i]; if(dis[y]>dis[x]+z) { dis[y]=dis[x]+z; p.push({-dis[y],y}); } } } } int main() { memset(dis,0x3f,sizeof(dis)); cin>>n>>m>>s>>t; for(int i=1;i<=m;i++) { cin>>x>>y>>v; add(x,y,v); add(y,x,v); } dij(s); if(dis[t]>=0x3f3f3f3f) cout<<-1<<endl; else cout<<dis[t]<<endl; return 0; }