题目链接:https://nanti.jisuanke.com/t/230
两个算法的主要思想都是松弛,就是两点间的距离通过第三点来变短
比如 1->3=10 1->2=2 2->3=5 这样你就可以通过2号点把1,3两点的距离缩短为7
Dijkstra算法被称为单源最短路,意思就是只能计算某个点到其他点的最短路,而Floyd算法
可以计算各个点之间的最短路径。
举个例子:有1~6 6个点 Dijkstra只能计算1号(或者2、3....其中某一个)点到其他点的最短路径
而Floyd算法就可以直接把1->2 1->3 .......任意两点之间的最短路都算出来
当然Floyd的时间复杂度是比Dijkstra高的。
首先来看Floyd算法
for (k=1;k<=n;k++)
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
if (e[i][j]>e[i][k]+e[k][j])
e[i][j]=e[i][k]+e[k][j];
使用K点对i,j两点进行缩短(松弛),当从 i 到 k 再从 k 到 j 的距离小于从 i 直接到 k 的距离是 i 到 j 的距离就被缩短。
最终的图就是一个全部为最短路的图
再看Dijkstra算法
首先来解释一下什么叫源,源其实就是起点,你想从哪一个点开始走的点。
单源最短就是单单这个点和其他各点的最短路。
因为是单源的所以我们就不必要设置一个二维数组,可以设置一个一位数组dis[],dis[i]表示的就是
源点到 i 的最短路径。
先上代码:
void dijkstra(){
bool book[maxn];
memset(book,0,sizeof(book));
int m;
for(int i=1;i<T;i++){
int min=INF;
for(int j=1;j<=T;j++){
if(!book[j] && dis[j]<min){
min=dis[j];
m=j;
}
}
book[m]=true;
for(int k=1;k<=T;k++){
if(dis[k]>dis[m]+e[m][k]) dis[k]=dis[m]+e[m][k];
}
}
}
主要思想就是:先找到一个和源点最近的点,这个点和源点之间肯定是最短路了(因为不可能通过第三个点进行松弛了(负权除外)),标记这个点已经找到它到源点最短路,然后通过这个点对其他各个点进行松弛。重复上述步骤,知道标记完所有的点。
题目的代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2505;
const int INF = 99999;
int e[maxn][maxn];
int T,C,Ts,Te;
int u,v,c;
int dis[maxn];
void init(){
cin>>T>>C>>Ts>>Te;
for(int i=1;i<=T;i++){
for(int j=1;j<=T;j++){
e[i][j]=INF;
}
}
for(int i=1;i<=T;i++){
e[i][i]=0;
}
for(int i=0;i<C;i++){
scanf("%d%d%d",&u,&v,&c);
e[v][u]=e[u][v]=c;
}
for(int i=1;i<=T;i++){
dis[i]=e[Ts][i];
}
}
void dijkstra(){
bool book[maxn];
memset(book,0,sizeof(book));
int m;
for(int i=1;i<T;i++){
int min=INF;
for(int j=1;j<=T;j++){
if(!book[j] && dis[j]<min){
min=dis[j];
m=j;
}
}
book[m]=true;
for(int k=1;k<=T;k++){
if(dis[k]>dis[m]+e[m][k]) dis[k]=dis[m]+e[m][k];
}
}
}
int main()
{
init();
dijkstra();
cout<<dis[Te];
}
完活!