最短路
- Dijkstra
这个算法感觉跟Prim找最小生成树的思想很像,都是利用贪心和dp的想法,只不过最短路更新的一直是权值和,而Prim每次只更新当前节点接下来延伸的边的最小值。
#include<iostream>
using namespace std;
const int MAXN = 100;
const int LIM = 0x3f3f3f3f;
struct MGragh//邻接矩阵
{
int matirx[MAXN][MAXN];
int numVertexes,numEdges;
};
void Djikstra(MGragh G,int v0,int *P,int *D){//P中存放的是最短路顶点前驱,D中存放的是每个顶点的最短路
int final[MAXN];
for(int i = 0;i<G.numVertexes;i++){
final[i] = 0;
D[i] = G.matirx[v0][i];
P[i] = 0;
}
D[v0] = 0;
final[v0] = 1;
for(int v = 1;v<G.numVertexes;v++){//主循环,找出v0到所有顶点的最短路
int min = LIM;
int k = -1;
for(int w = 0;w<G.numEdges;w++){//找出当前状态的最短路
if(!final[w]&&min<D[w]){
min = D[w];
k = w;
}
}
final[k] = 1;
for(int w = 0;w<G.numVertexes;w++){//更新加入最短路顶点的附近顶点的最短路
if(!final[w]&&min+G.matirx[k][w]<D[w]){
D[w] = min+G.matirx[k][w];
P[w] = k;
}
}
}
}
- Folyd
Djikstra有一个缺点就是不能找有负边图的最短路,这个算法解决了这个问题,时间复杂度为\(O(n^3)\),一次找到所有顶点的最短路。
const int MAXN = 100;
const int LIM = 100001;
struct Gragh
{
int matirx[MAXN][MAXN];
int numVertexs, numEdges;
};
void print(int P[][MAXN], int a, int b)//输出路径
{
cout<<a<<"->";
a = P[a][b];
while(a!=b)
{
cout<<a<<"->";
a = P[a][b];
}
cout<<b;
}
void shortestPath_Floyd(Gragh G, int D[][MAXN], int P[][MAXN])
{
//初始化
for (int i = 0; i<G.numVertexs; i++)
{
for (int j = 0; j<G.numVertexs; j++)
{
D[i][j] = G.matirx[i][j];
P[i][j] = j;
}
}
//主程序
for (int k = 0; k<G.numVertexs; k++)
for (int i = 0; i<G.numVertexs; i++)
for (int j = 0; j<G.numVertexs; j++)
if (D[i][j]>D[i][k] + D[k][j])
{
D[i][j] = D[i][k] + D[k][j];
P[i][j] = P[i][k];//可用P来迭代找到最短路径
}
print(P, 0, 8);
}