最短路径四种解法
最短路径四种解法
最短路径的四种解法
在学习“图”的时候,遇到过一道经典的题:最短路径。最短路径有四种最经典的解法。废话不多说,直接上代码。
弗洛伊德算法
//Floyd-Warshall
#include<iostream>
using namespace std;
const int M=999999;
int n,m,p1,p2,l;
int map[1000][1000];
int main()
{<!-- -->
cin>>n>>m;
for (int i=1;i<=n;i++)
{<!-- -->
for (int j=1;j<=n;j++)
{<!-- -->
if (i==j)
{<!-- -->
map[i][j]=0;
}
else
{<!-- -->
map[i][j]=M;
}
}
}
for (int i=1;i<=m;i++)
{<!-- -->
cin>>p1>>p2>>l;
map[p1][p2]=l;
}
for (int k = 1; k <= n; k++) {<!-- -->
for (int i = 1; i <= n; i++) {<!-- -->
for (int j = 1; j <= n; j++) {<!-- -->
if (map[i][j] > map[i][k] + map[k][j]) {<!-- -->
map[i][j] = map[i][k] + map[k][j];
}
}
}
}
for (int i=1;i<=n;i++)
{<!-- -->
for (int j=1;j<=n;j++)
{<!-- -->
cout<<map[i][j];
}
cout<<endl;
}
return 0;
}
弗洛伊德算法的时间复杂度O(n³),多源、无负权边,时效性较差。
迪杰斯特拉
//Dijkstra
#include <iostream>
using namespace std;
const int M=99999999;
int n,m,p1,p2,l,map[100][100],dis[1000],book[1000]={<!-- -->0},mi,u;
int main()
{<!-- -->
cin>>n>>m;
for (int i=1;i<=n;i++)
{<!-- -->
for (int j=1;j<=n;j++)
{<!-- -->
if (i==j)
{<!-- -->
map[i][j]=0;
}
else
{<!-- -->
map[i][j]=M;
}
}
}
for (int i=1;i<=m;i++)
{<!-- -->
cin>>p1>>p2>>l;
map[p1][p2]=l;
}
book[1]=1;
for (int i=1;i<=n;i++)
{<!-- -->
dis[i]=map[1][i];
}
for (int i=1;i<=n-1;i++)
{<!-- -->
mi=M;
for (int j=1;j<=n;j++)
{<!-- -->
if (dis[j]<mi&&book[j]==0)
{<!-- -->
mi=dis[j];
u=j;
}
}
book[u]=1;
for (int k=1;k<=n;k++)
{<!-- -->
if(map[u][k]<M)
{<!-- -->
if (dis[k]>dis[u]+map[u][k])
{<!-- -->
dis[k]=dis[u]+map[u][k];
}
}
}
}
for (int i=1;i<=n;i++)
{<!-- -->
cout<<dis[i]<<" ";
}
return 0;
}
迪杰斯特拉的时间复杂度O(n²),单源、无负权,时效性较好。
贝尔曼·福特
//Bellman-Ford
#include <iostream>
using namespace std;
const int M=9999999;
int main()
{<!-- -->
int n,m;
cin>>n>>m;
int p1[100],p2[100],l[100];
int dis[1000];
for (int i=1;i<=m;i++)
{<!-- -->
cin>>p1[i]>>p2[i]>>l[i];
}
for (int i=1;i<=n;i++)
{<!-- -->
dis[i]=M;
}
dis[1]=0;
for (int i=1;i<=n-1;i++)
{<!-- -->
for (int j=1;j<=m;j++)
{<!-- -->
if (dis[p2[i]]>dis[p1[i]]+l[i])
{<!-- -->
dis[p2[i]]=dis[p1[i]]+l[i];
}
}
}
for (int i=1;i<=n;i++)
{<!-- -->
cout<<dis[i]<<" ";
}
return 0;
}
贝尔曼·福特的时间复杂度O(n²),单源、可以判断是否为负权,时效性较好。
SPFA-贝尔曼·福特队列优化
//SPFA
#include <iostream>
using namespace std;
const int inf=9999999;
int main()
{<!-- -->
int n,m;
cin>>n>>m;
int p1[1000],p2[1000],l[1000];
int dis[1000];
int book[1000];
int first[1000];
int next[1000];
int que[1000]={<!-- -->0};
int tail=1,head=1;
int k;
for (int i=1;i<=n;i++)
{<!-- -->
dis[i]=inf;
}
dis[1]=0;
for (int i=1;i<=n;i++)
{<!-- -->
book[i]=0;
}
for (int i=1;i<=n;i++)
{<!-- -->
first[i]=-1;
}
int i;
for (i=1;i<=m;i++)
{<!-- -->
cin>>p1[i]>>p2[i]>>l[i];
next[i]=first[p1[i]];
first[p1[i]]=i;
}
que[tail]=1;
tail++;
book[i]=1;
while (head<tail)
{<!-- -->
k=first[que[head]];
while(k!=1)
{<!-- -->
if (dis[p2[k]]>dis[p1[k]]+l[k])
{<!-- -->
dis[p2[k]]=dis[p1[k]]+l[k];
}
if (book[p2[k]]==0)
{<!-- -->
que[tail]=p2[k];
tail++;
book[p2[k]]=1;
}
}
k=next[k];
head++;
}
for (i=1;i<=n;i++)
{<!-- -->
cout<<dis[i]<<" ";
}
return 0;
}
贝尔曼·福特队列优化的时间复杂度最大为O(nm),最小为O(n),单源、可以判断是否为负权,时效性相对好。 本文结束了,点个赞再走呗o( ̄▽ ̄)ブ</em>
转载于网络 侵权联系作者立即删除QAQ