一、多源最短路径Floyd
(1)定义:类似于贪心算法,每次确定最短路径的一个点然后维护(更新)这个点周围点的距离加入预选队列,等待下一次的抛出确定。
(2)思想
①邻接矩阵dist[i][j]
储存点与点的关系(注意初始化:点点没有直接相连为无穷大)
②状态转移方程
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j])
其中
dp[a][b]
的意思可以理解为点a到点b的最短路径,所以dp[i][k]
的意思可以理解为i到k的最短路径dp[k][j]
的意思为k到j的最短路径。(3)核心代码
for(int k=0;k<n;k++){ for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]); } } }
二、确定起点的最短路径Dijsktra
(1)定义:Dijkstra算法是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。
(2)思想:
迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。
const int N=1000; const int INF=1e9; int n; //当前图的点数 int vis[N]; //标记每个点被访问的情况 int dis[N]; //记录起点到各个顶点的最短路径长度 int prevnode[N]; //记录前驱顶点 int e[N][N]; //记录点与点权值的邻接矩阵
(3)核心代码
void Dijsktra(int start)//起点 { fill(vis,vis+N,0); //将顶点都标记为未访问 fill(dis,dis+N,INF); //将最短路径初始化为无穷大 fill(prevnode,prevnode+N,-1); //前驱顶点化为-1 dis[start]=0;//起点到自身距离为0 for(int i=0;i<n;i++){ //1 初始化 int node=-1; //记录当前从起点开始能找到的没被访问的最短点 int minn=INF; //记录当前最短路径 //2 从起点开始找到的没被访问的最短点 for(int j=0;j<n;j++){ if(vis[j]==0&&dis[j]<minn){ minn=dis[j],node=j; } } //3 找到后判断是否更新 if(node=-1) break;//没找到直接break vis[node]=1;//找到了就标记 for(int j=0;i<n;j++){ if(vis[j]==0&&e[node][j]!=INF&&(dis[node]+e[node][j]<dis[j])){ /* 如果结点未被访问 node能到达此结点 从起点到此结点j 经过node中介点 路程更短 */ dis[j]=dis[node]+e[node][j]; prevnode[j]=node; } } } }