最短路问题解法汇总
作者:互联网
图论的最短路问题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