ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

最短路问题解法汇总

2022-07-26 09:36:31  阅读:172  来源: 互联网

标签:idx int 短路 汇总 cin while dijkstra void 解法


图论的最短路问题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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有