最短路问题
最短路问题
最短路是图论里一个非常经典的问题。
单源最短路
我们这里使用比较出名的 Dijkstra 算法,时间复杂度
Dijkstra 朴素写法
算法步骤:
- 将距离数组设为 Inf,这里使用
。 - 将初始点设为
。 - 找到一个没有标记过且距离最短的点。
- 如果没有找到,则跳出函数。
- 标记该点,对该点的连边做松弛操作。
- 重复执行
。
Code1
#include <iostream>
using namespace std;
#define MAXN 10005
#define MAXM 500005
#define Inf 2147483647
int h[MAXN],tot,n,m;
int dis[MAXN];
bool vis[MAXN];
struct CFS
{
int to;
int nxt;
int wei;
CFS(){};
CFS(int t,int n,int w){
nxt=n;
to=t;
wei=w;
};
}edge[MAXM*2];
void addedge(int u,int v,int w)
{
tot++;
edge[tot]=CFS(v,h[u],w);
h[u]=tot;
return ;
}
void Dijkstra(int st)
{
for(int i=1;i<=n;i++) dis[i]=Inf;
dis[st]=0;
for(int i=1;i<=n;i++)
{
int min_d=Inf;
int v=0;
for(int j=1;j<=n;j++)
{
if(!vis[j]&&dis[j]<min_d)
{
min_d=dis[j];
v=j;
}
}
if(min_d==Inf) break;
vis[v]=true;
for(int j=h[v];j;j=edge[j].nxt) dis[edge[j].to]=min(dis[edge[j].to],dis[v]+edge[j].wei);
}
}
int main()
{
int st;
cin>>n>>m>>st;
for(int i=0;i<m;i++)
{
int u,v,w;
cin>>u>>v>>w;
addedge(u,v,w);
}
Dijkstra(st);
for(int i=1;i<=n;i++) cout<<dis[i]<<" ";
return 0;
}
Dijkstra 堆优化
主要将
Code2
#include <iostream>
#include <queue>
using namespace std;
#define MAXN 1005
#define MAXM 100005
#define Inf 0x3f3f3f3f
int h[MAXN],tot,n,m;
int dis[MAXN];
bool vis[MAXN];
struct CFS
{
int to;
int nxt;
int wei;
CFS(){};
CFS(int t,int n,int w){
nxt=n;
to=t;
wei=w;
};
}edge[MAXN];
void addedge(int u,int v,int w)
{
tot++;
edge[tot]=CFS(v,h[u],w);
h[u]=tot;
return ;
}
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > qu;
void Dijkstra(int st)
{
qu.push(make_pair(0,st));
while(qu.size())
{
int min_d=qu.top().first;
int v=qu.top().second;
qu.pop();
if(min_d!=dis[v]) continue;
for(int j=h[v];j;j=edge[j].nxt)
{
if(dis[edge[j].to]>dis[v]+edge[j].wei)
{
dis[edge[j].to]=dis[v]+edge[j].wei;
qu.push(make_pair(dis[edge[j].to],edge[j].to));
}
}
}
}
int main()
{
int st;
cin>>n>>m>>st;
for(int i=0;i<m;i++)
{
int u,v,w;
cin>>u>>v>>w;
addedge(u,v,w);
addedge(v,u,w);
}
Dijkstra(st);
for(int i=1;i<=n;i++) cout<<dis[i]<<" ";
return 0;
}
多源最短路
比较好于理解与编写的是 Floyd 算法。
Floyd
算法步骤:
- 本算法使用类似 DP 的写法。
Code3
#include <iostream>
#include <iomanip>
#include <string.h>
using namespace std;
int n,m;
int g[105][105];
void addedge(int u,int v,int w)
{
g[u][v]=w;
return ;
}
void Floyd()
{
for(int k=1;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]);
return ;
}
int main()
{
memset(g,0x3f,sizeof g);
cin>>n>>m;
for(int i=0;i<m;i++)
{
int u,v,w;
cin>>u>>v>>w;
addedge(u,v,w);
addedge(v,u,w);
}
Floyd();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j) cout<<setw(12)<<"0";
else cout<<setw(12)<<g[i][j];
}
cout<<endl;
}
return 0;
}
# input
6 5
1 2 3
2 6 8
6 5 1
2 3 5
3 6 1
# output
0 3 8 1061109567 10 9
3 0 5 1061109567 7 6
8 5 0 1061109567 2 1
1061109567 1061109567 1061109567 0 1061109567 1061109567
10 7 2 1061109567 0 1
9 6 1 1061109567 1 0
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 【.NET】调用本地 Deepseek 模型
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库