/*
Dijkstra:单源最短路径。第m+1近的结点与结点1的最短路径上的中间节点一定属于集合K,任意最短路径中间有一个不属于集合K的节点,则它的最短路径距离一定<第
m+1近的节点的最短路径长度,与距离与第m+1近的节点的最短路径已经确定、这样的结点属于集合K相矛盾。
最短路径 = 从结点1出发经最短路径集合中K中的节点P2 + <p2,Vn>
算法流程:
1)初始化,在集合K中加入结点1,结点1到结点1的最短距离为0,到其他结点距离为无穷大
2)遍历与集合K中结点直接相邻的边(U,V,C),其中U属于集合K,V不属于集合K,计算从结点1出发,按照已经得到的最短路径到达U,再由U经过该边到达V的路径长度。比较所有与集合K中直接相邻的非集合K中结点的
路径长度,路径长度最小的节点为下一个确定节点,将该结点加入集合K
3)若集合K中含有所有节点,结束
先更新距离,后挑选路径最短的节点加入,对于已经加入的节点需要直接跳过,通过vector来构建单链表
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <vector>
#define MAX 100
using namespace std;
typedef struct Edge
{
int _iNext;//下一个节点编号
int _iDistance;//从当前节点到下一个节点之间的距离
}Edge;
bool Mark[MAX];//标记是否已经是在已知节点集合
int Dist[MAX];//距离向量,为true表示最短记录。否则,表示经过中间节点的最短距离
int main(int argc)
{
int n,m,i,j,iVi,iVj,iDis;
vector<Edge> vecEdge[MAX];//用了100个数组,每个数组用来存放单链表信息
while(EOF!=scanf("%d %d",&n,&m))
{
//易错,n和m都为0的时候要退出
if(0==n && 0==m)
{
break;
}
//易错,要初始化邻接链表
for(i = 1 ; i <=n ; i++)
{
vecEdge[i].clear();
}
//获取每条边的信息
for(i = 0 ; i < m ; i++)
{
scanf("%d %d %d",&iVi,&iVj,&iDis);
//要构造一个结构体
Edge edge,edge2;
edge._iNext = iVj;
edge._iDistance = iDis;
edge2._iNext = iVi;
edge2._iDistance = iDis;
//由于是无向图,所以需要添加2条边
vecEdge[iVi].push_back(edge);
vecEdge[iVj].push_back(edge2);
}
//初始化
for(int i = 1 ; i < MAX; i++)
{
Mark[i] = false;
Dist[i] = -1;
}
Dist[1] = 0;//设置节点1的长度为0
Mark[1] = true;//设置节点1为已经加入集合
//易错,需要设置一个新节点
int iNewP = 1;
//遍历n-1趟,先更新距离,再挑选最短距离
for(i = 1 ; i < n ; i++)
{
for(j = 0 ; j < vecEdge[iNewP].size(); j++)
//for(j = 1 ; j < vecEdge[iNewP].size() ; j++)//遍历vector必须从0开始遍历
{
//取出边,判断与其相连的节点是否已经被标记
int iNext = vecEdge[iNewP][j]._iNext;
int iWeight = vecEdge[iNewP][j]._iDistance;
//如果已经属于集合K,则跳过
//if(iNext==true)
if(Mark[iNext]==true)
{
continue;
}
//如果距离不可达 或者走新加入节点的路径距离更短时,更新距离
if(Dist[iNext]==-1 || Dist[iNewP] + iWeight < Dist[iNext])
{
Dist[iNext] = Dist[iNewP] + iWeight;
}
}
//选择距离最短的结点,遍历所有节点
int min = 123123123;
for(j = 1 ; j <= n;j++)
{
//若其属于集合K,节点不可达,则跳过
if(Mark[j]==true || -1==Dist[j])
{
continue;
}
if(Dist[j] < min)
{
min = Dist[j];
iNewP = j;//更新加入的结点
}
}
//设置新加入的节点标记
Mark[iNewP] = true;
}
printf("%d\n",Dist[n]);
}
system("pause");
getchar();
return 0;
}
机试算法讲解: 第37题 Dijkstra
最新推荐文章于 2022-05-13 16:49:06 发布