最短路径问题
最短路径问题是图论中典型的问题,可用于解决管道铺设,线路安装,地图规划等路径问题。我们只需考虑有向图的算法,因为无向图是特殊的有向图,我们可以将所有的无向边u<->v,都拆分成两条有向边:u->v和u<-v,为了方便叙述,我们将图中的点数表示为n,图中的边数表示为m
图的存储
一般有两种存储方式:
-
邻接矩阵:使用二维数组,w[i] [j]表示点i和点j之间的边权。适用于边数较多的稠密图(当边的数量接近点的数量的平方)使用
//邻接矩阵数组,w[a][b] = c代表从a到b有权重为c的边,n为点数,m为边数 int [][]w = new int[n][n]; //加边操作 void add(int a,int b,int c){ w[a][b] = c; }
-
邻接表:邻接表有两种常用写法,第二种,代码更简洁,效率也更高:
-
二维List<List> edge,edge[i] [j]表示第i个点的第j条邻边
-
数组模拟邻接表:为每个点单独开一个单链表,分别存储该点的所有邻边。
int n,m;//点和边 int[] ne = new int[m];//存储下一个节点 int[] he = new int[n];//存储头节点的链表 int[] e = new int[m];//存储终点节点 int[] w = new int[m];//存储权重 int idx;//这里也有一个关键点,idx在类中定义并且不进行赋值,在方法中进行调用,并且在psvm中运行该方法是不会报错的,并且初始值为0 //a为起点,b为终点,c为权重 void add(int a,int b,int c){ e[idx] = b; ne[idx] = he[a]; he[a] = idx; w[idx] = c; idx++; }
-
单源最短路+模板
Djikstra算法
最裸的djikstra算法,不使用堆优化
图用邻接矩阵处理
只有所有边的权值为正时才可以使用。稠密图上的时间复杂度为O(n ^ 2),稀疏图上的时间复杂度是O(n^2)
int n,m;
int[][] w = new int[n][n];//存储图的邻接矩阵
int[] dis = new int[n];//dist[]表示每个点到起点的距离
boolean[] keep = new boolean[n];//存储每个点的最短距离是否已经确认
public void djikstra(){
for(int i = 0;i < n;i++){
//给每个点的距离赋值无穷大
dis[i] = 0x3f3f3f3f;
}
dis[1] = 0;
for(int i = 0;i < n;i++){
int t = -1;
//先给第一个节点进行赋值
for(int j = 1;j <= n;j++){
if(!keep[j]&&(t == -1||dis[j]<dis[t])){
t = j;
}
}
//确认为最短时候更新状态以及余下的节点
keep[t] = true;
for(int j = 1;j<=n;j++){
dis[j] = Math.min(dis[j],dis[t]+w[t][j]);
}
}
}
Djikstra算法+heap优化
使用邻接表
用堆来维护所有点到起点的距离,时间复杂度为O(nlogn)
class Solution {
int[] ne = new int[6001];
int[] he =