其他分享
首页 > 其他分享> > 最短路问题解法汇总

最短路问题解法汇总

作者:互联网

图论的最短路问题4种方法结合(亲测可过)

dijkstra 算法

基础版,我认为对于算法思想很有帮助,但是性能一般(doge)

#include<bits/stdc++.h>
using namespace std;
const int N=510,INF =0x3f3f3f3f;
int n,m; //points and angles
int g[N][N]; //邻接矩阵
int d[N]; //the distance from 1 to others
int st[N];
void dijkstra()
{
	memset(d,0x3f,sizeof d);
	d[1]=0;
	for(int i=0;i<n;i++)
	{
		int t=-1;
		for(int j=1;j<=n;j++)
		    if(!st[j]&&(t==-1||d[t]>d[j]))
				t=j;
		st[t]=true;
		for(int j=1;j<=n;j++)
			d[j]=min(d[j],d[t]+g[t][j]);
	}
}
int main()
{
	memset(g,0x3f,sizeof g);
	cin>>n>>m;
	while(m--)
	{
		int a,b,c; cin>>a>>b>>c;
		g[a][b]=min(g[a][b],c);
	}
	dijkstra();
	for(int i=1;i<=n;i++) cout<<d[i]<<" ";
 	return 0;
}

dijkstra 堆优化版 算法

强烈推荐,实用性很强

#include<bits/stdc++.h>
using namespace std;
//详细注解见朴素dijkstra
const int N=100010,INF=0X3f3f3f3f;
typedef pair<int,int> PII;
int n,m,k;
int h[N],e[N],w[N],ne[N],idx;
int d[N];
void add(int a,int b,int c)
{
	e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
void dijkstra()
{
	priority_queue<PII,vector<PII>,greater<PII> > q;
	memset(d,0x3f,sizeof d); d[1]=0;
	q.push({0,k});
	while(!q.empty())
	{
		PII t=q.top(); q.pop();
		int dt=t.first,p=t.second;
		for(int i=h[p];i!=-1;i=ne[i])
		{
			int j=e[j];
			if(d[j]>dt+w[i])
			{
				d[j]=dt+w[i];
				q.push({d[j],j});
			}
		}
	}
}
int main()
{
	memset(h,-1,sizeof h);
	cin>>n>>m>>k;
	while(m--){
		int a,b,c; cin>>a>>b>>c;
		add(a,b,c);
	}
	dijkstra();
	for(int i=1;i<=n;i++) cout<<d[i]<<" ";
	return 0;
}

bellman_ford 算法

使用比较少,但是同样很重要 《很重要》

#include<bits/stdc++.h>
using namespace std;
const int N=100010,INF=0x3f3f3f3f;
int n,m,k;
int d[N],back[N];
struct edge{
	int s,v,w;
}e[N];
int bellman_ford()
{
	memset(d,0x3f,sizeof d);
	d[1]=0;
	for(int j=0;j<k;j++)
	{
		memcpy(back,d,sizeof d);
	    for(int i=0;i<m;i++)
	    {
			int s=e[i].s,v=e[i].v,w=e[i].v;
			d[v]=min(d[v],back[s]+w);
		}
	}
	return d[n];
}
int main()
{
	cin>>n>>m>>k;
	for(int i=0;i<m;i++)
	{
		int a,b,c; cin>>a>>b>>c;
		e[i]={a,b,c};
	}
	int ans=bellman_ford();
	if(ans>=INF>>1) puts("impossible");
	else cout<<d[n];
	return 0;
}

spfa 算法

在 90% 的情况下可以过,个人认为很万能
很像bfs

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int n,m,k=1;
int h[N],e[N],w[N],ne[N],idx;
int d[N];
bool st[N];
void add(int a,int b,int c)
{
	e[idx]=b;
	w[idx]=c;
	ne[idx]=h[a];
	h[a]=idx++;
}
void spfa()
{
	memset(d,0x3f,sizeof d); d[k]=0;
	queue<int> q; q.push(k);
	st[k]=true;
	while(!q.empty())
	{
		int t=q.front(); q.pop();
		for(int i=h[t];i!=-1;i=ne[i])
		{
			int j=e[i];
			if(!st[j])
			{
				q.push(j);
				st[t]=true;
				if(d[j]>d[t]+w[i])
		  		    d[j]=d[t]+w[i];
			}
		}
	}
}
int main()
{
	memset(h,-1,sizeof h);
	cin>>n>>m;
	while(m--)
	{
		int a,b,c; cin>>a>>b>>c;
		add(a,b,c);
	}
	spfa();
	for(int i=1;i<=n;i++) cout<<d[i]<<" ";
	return 0;
}

Floyd 算法

看数据范围后再使用!
这是基于动态规划的代码,所以你看起来会觉得这是不是区间dp?

#include<bits/stdc++.h>
using namespace std;
const int N=510,INF=0x3f3f3f3f;
int n,m,k;
int d[N][N];
void Floyd()
{
	for(int i=1;i<=n;i++)
	    for(int k=1;k<=n;k++)
			for(int j=1;j<=n;j++)
				d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
int main()
{
	memset(d,0x3f,sizeof d);
	cin>>n>>m>>k;
	while(m--)
	{
		int a,b,c; cin>>a>>b>>c;
		d[a][b]=min(d[a][b],c);
	}
	Floyd();
 	while(k--)
 	{
 		int x,y; cin>>x>>y;
 		if(x==y) cout<<0<<endl;
 		else
 		{
 			if(d[x][y]>=INF>>1) puts("impossible");
 			else cout<<d[x][y]<<endl;
 		}
	}
	return 0;
}

如果还有问题,请在评论区留言

改进日志:
2021/12/18 改正了dijkstra的读入
2022/03/06 改善了算法解释

标签:idx,int,短路,汇总,cin,while,dijkstra,void,解法
来源: https://www.cnblogs.com/Angelqbs8198115/p/16519618.html