最短路

最短路

一.算法

1.Dijksra

仅适用于起点确定边权非负的情况
时间复杂度\(O(mlog_m)\)

流程

  1. 从起点开始,每次找到没有被确定最短路的最近的点
  2. 确定到该点的最短路
  3. 重复执行到所有点都被确定

代码示例

#include<bits/stdc++.h>
#define zyy pair<int,int>
#define int long long
using namespace std;
const int N=2e5+10;
vector<zyy>g[N];
int dis[N];
signed main(){
	int n,m,s;
	cin>>n>>m>>s;
	for(int i=1;i<=m;i++){
		int u,v,w;
		cin>>u>>v>>w;
		g[u].push_back({v,w});
		//g[v].push_back({u,w});双向边 
	}
	memset(dis,0x3f,sizeof dis);
	priority_queue<zyy,vector<zyy>,greater<zyy>>q;
	q.push({0,s});
	dis[s]=0;
	while(q.size()){
		auto [w,u]=q.top();
		q.pop();
		if(dis[u]<w){
			continue;
		}
		for(auto [v,ww]:g[u]){
			if(dis[v]>ww+w){
				dis[v]=ww+w;
				//pre[v]=u;v的前一个点 
				q.push({ww+w,v});
			}
		}
	}
	for(int i=1;i<=n;i++){		
		cout<<dis[i]<<" "; 
	}
	return 0;
}

可计算的杂项

完整路径

加上前驱即可

路径条数
int cnt[N];
priority_queue<zyy,vector<zyy>,greater<zyy>>q;
q.push({0,s});
dis[s]=0;
cnt[s]=1;
while(q.size()){
	auto [w,u]=q.top();
	q.pop();
	if(dis[u]<w){
		continue;
	}
	for(auto [v,ww]:g[u]){
		if(dis[v]>ww+w){
			dis[v]=ww+w;
			cnt[v]=cnt[u];
			q.push({ww+w,v});
		}
		if(dis[v]==ww+w){
			cnt[v]+=cnt[u];
		}
	}
}

2.Floyd

可处理多源最短路,时间复杂度 \(O(n^3)\)

流程

  • 枚举一个中转点k
  • \(i-j\)的最短路显然可以拆分为 \(i-k\)\(k-j\)的最短路
  • 取最小值即可

代码示例

#include<bits/stdc++.h>
using namespace std;
int dp[105][105];
int main(){
	int n,m;
	cin>>n>>m;
	memset(dp,0x3f,sizeof dp);
	for(int i=1;i<=n;i++){
		dp[i][i]=0;
	}
	for(int i=1;i<=m;i++){
		int u,v,w;
		cin>>u>>v>>w;
		dp[u][v]=dp[v][u]=min(dp[u][v],w);
	}
	
	for(int k=1;k<=n;k++){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cout<<dp[i][j]<<" ";
		}
		cout<<"\n";
	}
	return 0; 
} 

posted @ 2026-07-06 15:45  diaitor  阅读(2)  评论(0)    收藏  举报