最短路径
最短路径分为迪杰斯特拉与弗洛伊德算法,且听我娓娓道来。
单源最短路径——迪杰斯特拉
#include <iostream>
#include <cstring>
using namespace std;
const int MAXVEX = 105;
const int INFINITY = 65535;
struct MGraph{
int arc[MAXVEX][MAXVEX];
int vexes[MAXVEX];
int numVertexes,numEdges;
};
void CreateMGraph(MGraph *G){
cout<<"输入顶点个数与边的个数";
cin>>G->numVertexes>>G->numEdges;
cout<<"输入顶点信息:";
for(int i=0;i<G->numVertexes;i++){
cin>>G->vexes[i];
}
for(int i=0;i<G->numVertexes;i++){
for(int j=0;j<G->numVertexes;j++){
if(i == j) G->arc[i][j] = 0;
else G->arc[i][j] = INFINITY;
}
}
cout<<"输入边的信息:";
for(int i=0;i<G->numEdges;i++){
int j,k,l;
cin>>j>>k>>l;
G->arc[j][k] = l;
G->arc[k][j] = G->arc[j][k];
}
}
int D[MAXVEX] = {0};//用于存储从v0到各个顶点的最短路径
int P[MAXVEX] = {0};//用于存储自v0前往各个顶点的路径
bool final[MAXVEX];
void Dijkstra(MGraph *G,int v0){
memset(final,false,sizeof(final));
//下方进行初始化操作
for(int i=0;i<G->numVertexes;i++){
D[i] = G->arc[v0][i];//D数组记录的是从v0到v的距离
P[i] = 0;//P记录最短路径
}
final[v0] = true;//表示v0顶点的最短路径已经找到 (即它本身)
for(int v=0;v<G->numVertexes;v++){//对所有顶点进行遍历
int MIN = INFINITY,k;//k记录当前最短路径(v0,v)中v的下标
for(int w=0;w<G->numVertexes;w++){//寻找自v0到某顶点的最短路径
if(!final[w]&&D[w]<MIN){//记住:D数组记录的是从v0到
//数组下标顶点的最短路径。
MIN = D[w];
k = w;
}
}
final[k] = true;
//下面通过得到的MIN值松弛D数组
//MIN值的意义是自v0到k的距离,这个距离已经是最短的了
for(int w=0;w<G->numVertexes;w++){
if(!final[w]&&MIN+G->arc[k][w]<D[w]){
D[w] = MIN + G->arc[k][w];
P[w] = k;
}
} /*看似最外层的循环变量v在整个内部循环中都没有起到
作用,但每经过一次循环,D数组中的数值都得到了松弛。*/
}
}
int main()
{
MGraph G;
CreateMGraph(&G);
Dijkstra(&G,0);
for(int i=0;i<G.numVertexes;i++){
cout<<D[i]<<' ';
}
return 0;
}
思想是通过一个外层循环,每次找到当前最短路径,并用这个最短路径松弛其他顶点,得到整张图的单源最短路径,时间复杂度为O(n ^ 2)。
多元最短路径——弗洛伊德算法
弗洛伊德算法使用三重循环,非常巧妙的求出了邻接矩阵每一个顶点到另外所有顶点的最短路径,当然时间复杂度为O(n ^ 3),参与竞赛的朋友请在数据小于200时(200左右也勉强可以)使用。
#include <iostream>
#include <cstring>
using namespace std;
const int MAXVEX = 105;
const int INFINITY = 65535;
struct MGraph{
int arc[MAXVEX][MAXVEX];
int vexes[MAXVEX];
int numVertexes,numEdges;
};
void CreateMGraph(MGraph *G){
cout<<"输入顶点个数与边的个数";
cin>>G->numVertexes>>G->numEdges;
cout<<"输入顶点信息:";
for(int i=0;i<G->numVertexes;i++){
cin>>G->vexes[i];
}
for(int i=0;i<G->numVertexes;i++){
for(int j=0;j<G->numVertexes;j++){
if(i == j) G->arc[i][j] = 0;
else G->arc[i][j] = INFINITY;
}
}
cout<<"输入边的信息:";
for(int i=0;i<G->numEdges;i++){
int j,k,l;
cin>>j>>k>>l;
G->arc[j][k] = l;
G->arc[k][j] = G->arc[j][k];
}
}
int D[MAXVEX][MAXVEX] = {0};
int P[MAXVEX][MAXVEX] = {0};
void Floyd(MGraph *G){
//两个循环完成初始化操作
for(int i=0;i<G->numVertexes;i++){
for(int j=0;j<G->numVertexes;j++){
D[i][j] = G->arc[i][j];
P[i][j] = j;
}
}
//Floyd算法太完美了,没有什么好说明的,一切尽在代码中
for(int k=0;k<G->numVertexes;k++){//最外层循环用于寻找中继结点
for(int v=0;v<G->numVertexes;v++){
for(int w=0;w<G->numVertexes;w++){
if(D[v][w]>D[v][k]+D[k][w]){
D[v][w] = D[v][k]+D[k][w];
P[v][w] = P[v][k];
}
}
}
}//时间复杂度O(n ^ 3),不断松弛D数组以求得多元最短路径
}
//用于打印邻接矩阵最短路径的函数ShowPath()
void ShowPath(MGraph *G)
{
for(int v=0;v<G->numVertexes;v++){
for(int w=v+1;w<G->numVertexes;w++){//w的循环值为v+1,没有必要重复打印路径
cout<<"("<<v<<","<<w<<")-weight:"<<D[v][w];
cout<<endl<<"Path:"<<v<<"->";
int k = P[v][w];
while(k!=w){
cout<<k;
k = P[k][w];
cout<<"->";
}
cout<<w;
cout<<endl;
}
cout<<endl;
}
}
int main()
{
MGraph G;
CreateMGraph(&G);
Floyd(&G);
ShowPath(&G);
return 0;
}