class064 Dijkstra算法、分层图最短路【算法】

class064 Dijkstra算法、分层图最短路【算法】

算法讲解064【必备】Dijkstra算法、分层图最短路
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

code1 743. 网络延迟时间

// Dijkstra算法模版(Leetcode)
// 网络延迟时间
// 有 n 个网络节点,标记为 1 到 n
// 给你一个列表 times,表示信号经过 有向 边的传递时间
// times[i] = (ui, vi, wi),表示从ui到vi传递信号的时间是wi
// 现在,从某个节点 s 发出一个信号
// 需要多久才能使所有节点都收到信号
// 如果不能使所有节点收到信号,返回 -1
// 测试链接 : https://leetcode.cn/problems/network-delay-time

code1 P4779 【模板】单源最短路径(标准版)

// Dijkstra算法模版(洛谷)
// 静态空间实现 : 链式前向星 + 反向索引堆
// 测试链接 : https://www.luogu.com.cn/problem/P4779
// 请同学们务必参考如下代码中关于输入、输出的处理
// 这是输入输出处理效率很高的写法
// 提交以下所有代码,把主类名改成Main,可以直接通过

package class064;// Dijkstra算法模版(洛谷)
// 静态空间实现 : 链式前向星 + 反向索引堆
// 测试链接 : https://www.luogu.com.cn/problem/P4779
// 请同学们务必参考如下代码中关于输入、输出的处理
// 这是输入输出处理效率很高的写法
// 提交以下所有代码,把主类名改成Main,可以直接通过import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Arrays;public class Code01_DijkstraLuogu {public static int MAXN = 100001;public static int MAXM = 200001;// 链式前向星public static int[] head = new int[MAXN];public static int[] next = new int[MAXM];public static int[] to = new int[MAXM];public static int[] weight = new int[MAXM];public static int cnt;// 反向索引堆public static int[] heap = new int[MAXN];// where[v] = -1,表示v这个节点,从来没有进入过堆// where[v] = -2,表示v这个节点,已经弹出过了// where[v] = i(>=0),表示v这个节点,在堆上的i位置public static int[] where = new int[MAXN];public static int heapSize;public static int[] distance = new int[MAXN];public static int n, m, s;public static void build() {cnt = 1;heapSize = 0;Arrays.fill(head, 1, n + 1, 0);Arrays.fill(where, 1, n + 1, -1);Arrays.fill(distance, 1, n + 1, Integer.MAX_VALUE);}// 链式前向星建图public static void addEdge(int u, int v, int w) {next[cnt] = head[u];to[cnt] = v;weight[cnt] = w;head[u] = cnt++;}public static void addOrUpdateOrIgnore(int v, int w) {if (where[v] == -1) {heap[heapSize] = v;where[v] = heapSize++;distance[v] = w;heapInsert(where[v]);} else if (where[v] >= 0) {distance[v] = Math.min(distance[v], w);heapInsert(where[v]);}}public static void heapInsert(int i) {while (distance[heap[i]] < distance[heap[(i - 1) / 2]]) {swap(i, (i - 1) / 2);i = (i - 1) / 2;}}public static int pop() {int ans = heap[0];swap(0, --heapSize);heapify(0);where[ans] = -2;return ans;}public static void heapify(int i) {int l = 1;while (l < heapSize) {int best = l + 1 < heapSize && distance[heap[l + 1]] < distance[heap[l]] ? l + 1 : l;best = distance[heap[best]] < distance[heap[i]] ? best : i;if (best == i) {break;}swap(best, i);i = best;l = i * 2 + 1;}}public static boolean isEmpty() {return heapSize == 0;}public static void swap(int i, int j) {int tmp = heap[i];heap[i] = heap[j];heap[j] = tmp;where[heap[i]] = i;where[heap[j]] = j;}public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));StreamTokenizer in = new StreamTokenizer(br);PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));while (in.nextToken() != StreamTokenizer.TT_EOF) {n = (int) in.nval;in.nextToken(); m = (int) in.nval;in.nextToken(); s = (int) in.nval;build();for (int i = 0, u, v, w; i < m; i++) {in.nextToken(); u = (int) in.nval;in.nextToken(); v = (int) in.nval;in.nextToken(); w = (int) in.nval;addEdge(u, v, w);}dijkstra();out.print(distance[1]);for (int i = 2; i <= n; i++) {out.print(" " + distance[i]);}out.println();}out.flush();out.close();br.close();}public static void dijkstra() {addOrUpdateOrIgnore(s, 0);while (!isEmpty()) {int v = pop();for (int ei = head[v]; ei > 0; ei = next[ei]) {addOrUpdateOrIgnore(to[ei], distance[v] + weight[ei]);}}}}

code2 1631. 最小体力消耗路径

// 最小体力消耗路径
// 你准备参加一场远足活动。给你一个二维 rows x columns 的地图 heights
// 其中 heights[row][col] 表示格子 (row, col) 的高度
// 一开始你在最左上角的格子 (0, 0) ,且你希望去最右下角的格子 (rows-1, columns-1)
// (注意下标从 0 开始编号)。你每次可以往 上,下,左,右 四个方向之一移动
// 你想要找到耗费 体力 最小的一条路径
// 一条路径耗费的体力值是路径上,相邻格子之间高度差绝对值的最大值
// 请你返回从左上角走到右下角的最小 体力消耗值
// 测试链接 :https://leetcode.cn/problems/path-with-minimum-effort/

package class064;import java.util.PriorityQueue;// 最小体力消耗路径
// 你准备参加一场远足活动。给你一个二维 rows x columns 的地图 heights
// 其中 heights[row][col] 表示格子 (row, col) 的高度
// 一开始你在最左上角的格子 (0, 0) ,且你希望去最右下角的格子 (rows-1, columns-1) 
// (注意下标从 0 开始编号)。你每次可以往 上,下,左,右 四个方向之一移动
// 你想要找到耗费 体力 最小的一条路径
// 一条路径耗费的体力值是路径上,相邻格子之间高度差绝对值的最大值
// 请你返回从左上角走到右下角的最小 体力消耗值
// 测试链接 :https://leetcode.cn/problems/path-with-minimum-effort/
public class Code02_PathWithMinimumEffort {// 0:上,1:右,2:下,3:左public static int[] move = new int[] { -1, 0, 1, 0, -1 };public int minimumEffortPath(int[][] heights) {// (0,0)源点// -> (x,y)int n = heights.length;int m = heights[0].length;int[][] distance = new int[n][m];for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {distance[i][j] = Integer.MAX_VALUE;}}distance[0][0] = 0;boolean[][] visited = new boolean[n][m];// 0 : 格子的行// 1 : 格子的列// 2 : 源点到当前格子的代价PriorityQueue<int[]> heap = new PriorityQueue<int[]>((a, b) -> a[2] - b[2]);heap.add(new int[] { 0, 0, 0 });while (!heap.isEmpty()) {int[] record = heap.poll();int x = record[0];int y = record[1];int c = record[2];if (visited[x][y]) {continue;}if (x == n - 1 && y == m - 1) {// 常见剪枝// 发现终点直接返回// 不用等都结束return c;}visited[x][y] = true;for (int i = 0; i < 4; i++) {int nx = x + move[i];int ny = y + move[i + 1];if (nx >= 0 && nx < n && ny >= 0 && ny < m && !visited[nx][ny]) {int nc = Math.max(c, Math.abs(heights[x][y] - heights[nx][ny]));if (nc < distance[nx][ny]) {distance[nx][ny] = nc;heap.add(new int[] { nx, ny, nc });}}}}return -1;}}

code3 778. 水位上升的泳池中游泳

// 水位上升的泳池中游泳
// 在一个 n x n 的整数矩阵 grid 中
// 每一个方格的值 grid[i][j] 表示位置 (i, j) 的平台高度
// 当开始下雨时,在时间为 t 时,水池中的水位为 t
// 你可以从一个平台游向四周相邻的任意一个平台,但是前提是此时水位必须同时淹没这两个平台
// 假定你可以瞬间移动无限距离,也就是默认在方格内部游动是不耗时的
// 当然,在你游泳的时候你必须待在坐标方格里面。
// 你从坐标方格的左上平台 (0,0) 出发
// 返回 你到达坐标方格的右下平台 (n-1, n-1) 所需的最少时间
// 测试链接 : https://leetcode.cn/problems/swim-in-rising-water/

package class064;import java.util.PriorityQueue;// 水位上升的泳池中游泳
// 在一个 n x n 的整数矩阵 grid 中
// 每一个方格的值 grid[i][j] 表示位置 (i, j) 的平台高度
// 当开始下雨时,在时间为 t 时,水池中的水位为 t
// 你可以从一个平台游向四周相邻的任意一个平台,但是前提是此时水位必须同时淹没这两个平台
// 假定你可以瞬间移动无限距离,也就是默认在方格内部游动是不耗时的
// 当然,在你游泳的时候你必须待在坐标方格里面。
// 你从坐标方格的左上平台 (0,0) 出发
// 返回 你到达坐标方格的右下平台 (n-1, n-1) 所需的最少时间
// 测试链接 : https://leetcode.cn/problems/swim-in-rising-water/
public class Code03_SwimInRisingWater {// 0:上,1:右,2:下,3:左public static int[] move = new int[] { -1, 0, 1, 0, -1 };public static int swimInWater(int[][] grid) {int n = grid.length;int m = grid[0].length;int[][] distance = new int[n][m];for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {distance[i][j] = Integer.MAX_VALUE;}}distance[0][0] = grid[0][0];boolean[][] visited = new boolean[n][m];// 0 : 格子的行// 1 : 格子的列// 2 : 源点到当前格子的代价PriorityQueue<int[]> heap = new PriorityQueue<>((a, b) -> a[2] - b[2]);heap.add(new int[] { 0, 0, grid[0][0] });while (!heap.isEmpty()) {int x = heap.peek()[0];int y = heap.peek()[1];int c = heap.peek()[2];heap.poll();if (visited[x][y]) {continue;}visited[x][y] = true;if (x == n - 1 && y == m - 1) {// 常见剪枝// 发现终点直接返回// 不用等都结束return c;}for (int i = 0, nx, ny, nc; i < 4; i++) {nx = x + move[i];ny = y + move[i + 1];if (nx >= 0 && nx < n && ny >= 0 && ny < m && !visited[nx][ny]) {nc = Math.max(c, grid[nx][ny]);if (nc < distance[nx][ny]) {distance[nx][ny] = nc;heap.add(new int[] { nx, ny, nc });}}}}return -1;}}

code4 864. 获取所有钥匙的最短路径

// 获取所有钥匙的最短路径
// 给定一个二维网格 grid ,其中:
// ‘.’ 代表一个空房间、‘#’ 代表一堵、‘@’ 是起点
// 小写字母代表钥匙、大写字母代表锁
// 从起点开始出发,一次移动是指向四个基本方向之一行走一个单位空间
// 不能在网格外面行走,也无法穿过一堵墙
// 如果途经一个钥匙,我们就把它捡起来。除非我们手里有对应的钥匙,否则无法通过锁。
// 假设 k 为 钥匙/锁 的个数,且满足 1 <= k <= 6,
// 字母表中的前 k 个字母在网格中都有自己对应的一个小写和一个大写字母
// 换言之,每个锁有唯一对应的钥匙,每个钥匙也有唯一对应的锁
// 另外,代表钥匙和锁的字母互为大小写并按字母顺序排列
// 返回获取所有钥匙所需要的移动的最少次数。如果无法获取所有钥匙,返回 -1 。
// 测试链接:https://leetcode.cn/problems/shortest-path-to-get-all-keys

package class064;// 获取所有钥匙的最短路径
// 给定一个二维网格 grid ,其中:
// '.' 代表一个空房间、'#' 代表一堵、'@' 是起点
// 小写字母代表钥匙、大写字母代表锁
// 从起点开始出发,一次移动是指向四个基本方向之一行走一个单位空间
// 不能在网格外面行走,也无法穿过一堵墙
// 如果途经一个钥匙,我们就把它捡起来。除非我们手里有对应的钥匙,否则无法通过锁。
// 假设 k 为 钥匙/锁 的个数,且满足 1 <= k <= 6,
// 字母表中的前 k 个字母在网格中都有自己对应的一个小写和一个大写字母
// 换言之,每个锁有唯一对应的钥匙,每个钥匙也有唯一对应的锁
// 另外,代表钥匙和锁的字母互为大小写并按字母顺序排列
// 返回获取所有钥匙所需要的移动的最少次数。如果无法获取所有钥匙,返回 -1 。
// 测试链接:https://leetcode.cn/problems/shortest-path-to-get-all-keys
public class Code04_ShortestPathToGetAllKeys {public static int MAXN = 31;public static int MAXM = 31;public static int MAXK = 6;// 0:上,1:右,2:下,3:左public static int[] move = new int[] { -1, 0, 1, 0, -1 };public static char[][] grid = new char[MAXN][];public static boolean[][][] visited = new boolean[MAXN][MAXM][1 << MAXK];// 0 : 行// 1 : 列// 2 : 收集钥匙的状态public static int[][] queue = new int[MAXN * MAXM * (1 << MAXK)][3];public static int l, r, n, m, key;public static void build(String[] g) {l = r = key = 0;n = g.length;m = g[0].length();for (int i = 0; i < n; i++) {grid[i] = g[i].toCharArray();}for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (grid[i][j] == '@') {queue[r][0] = i;queue[r][1] = j;// 0 : 000000queue[r++][2] = 0;}if (grid[i][j] >= 'a' && grid[i][j] <= 'f') {key |= 1 << (grid[i][j] - 'a');}}}for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {for (int s = 0; s <= key; s++) {visited[i][j][s] = false;}}}}public static int shortestPathAllKeys(String[] g) {build(g);int level = 1;while (l < r) {for (int k = 0, size = r - l, x, y, s; k < size; k++) {x = queue[l][0];y = queue[l][1];s = queue[l++][2];for (int i = 0, nx, ny, ns; i < 4; i++) {nx = x + move[i];ny = y + move[i + 1];ns = s;if (nx < 0 || nx == n || ny < 0 || ny == m || grid[nx][ny] == '#') {// 越界或者障碍continue;}if (grid[nx][ny] >= 'A' && grid[nx][ny] <= 'F' && ((ns & (1 << (grid[nx][ny] - 'A'))) == 0)) {// 是锁,又没有对应的钥匙continue;}if (grid[nx][ny] >= 'a' && grid[nx][ny] <= 'f') {// 是某一把钥匙ns |= (1 << (grid[nx][ny] - 'a'));}if (ns == key) {// 常见剪枝// 发现终点直接返回// 不用等都结束return level;}if (!visited[nx][ny][ns]) {visited[nx][ny][ns] = true;queue[r][0] = nx;queue[r][1] = ny;queue[r++][2] = ns;}}}level++;}return -1;}}

code5 LCP 35. 电动车游城市

// 电动车游城市
// 小明的电动车电量充满时可行驶距离为 cnt,每行驶 1 单位距离消耗 1 单位电量,且花费 1 单位时间
// 小明想选择电动车作为代步工具。地图上共有 N 个景点,景点编号为 0 ~ N-1
// 他将地图信息以 [城市 A 编号,城市 B 编号,两城市间距离] 格式整理在在二维数组 paths,
// 表示城市 A、B 间存在双向通路。
// 初始状态,电动车电量为 0。每个城市都设有充电桩,
// charge[i] 表示第 i 个城市每充 1 单位电量需要花费的单位时间。
// 请返回小明最少需要花费多少单位时间从起点城市 start 抵达终点城市 end
// 测试链接 : https://leetcode.cn/problems/DFPeFJ/

package class064;import java.util.ArrayList;
import java.util.PriorityQueue;// 电动车游城市
// 小明的电动车电量充满时可行驶距离为 cnt,每行驶 1 单位距离消耗 1 单位电量,且花费 1 单位时间
// 小明想选择电动车作为代步工具。地图上共有 N 个景点,景点编号为 0 ~ N-1
// 他将地图信息以 [城市 A 编号,城市 B 编号,两城市间距离] 格式整理在在二维数组 paths,
// 表示城市 A、B 间存在双向通路。
// 初始状态,电动车电量为 0。每个城市都设有充电桩,
// charge[i] 表示第 i 个城市每充 1 单位电量需要花费的单位时间。
// 请返回小明最少需要花费多少单位时间从起点城市 start 抵达终点城市 end
// 测试链接 : https://leetcode.cn/problems/DFPeFJ/
public class Code05_VisitCityMinCost {// 电动车总电量,cntpublic static int electricCarPlan(int[][] paths, int cnt, int start, int end, int[] charge) {int n = charge.length;ArrayList<ArrayList<int[]>> graph = new ArrayList<>();for (int i = 0; i < n; i++) {graph.add(new ArrayList<>());}for (int[] path : paths) {graph.get(path[0]).add(new int[] { path[1], path[2] });graph.get(path[1]).add(new int[] { path[0], path[2] });}// n : 0 ~ n-1,不代表图上的点// (点,到达这个点的电量)图上的点!int[][] distance = new int[n][cnt + 1];for (int i = 0; i < n; i++) {for (int j = 0; j <= cnt; j++) {distance[i][j] = Integer.MAX_VALUE;}}distance[start][0] = 0;boolean[][] visited = new boolean[n][cnt + 1];// 0 : 当前点// 1 : 来到当前点的电量// 2 : 花费时间PriorityQueue<int[]> heap = new PriorityQueue<int[]>((a, b) -> (a[2] - b[2]));heap.add(new int[] { start, 0, 0 });while (!heap.isEmpty()) {int[] record = heap.poll();int cur = record[0];int power = record[1];int cost = record[2];if (visited[cur][power]) {continue;}if (cur == end) {// 常见剪枝// 发现终点直接返回// 不用等都结束return cost;}visited[cur][power] = true;if (power < cnt) {// 充一格电// cur, power+1if (!visited[cur][power + 1] && cost + charge[cur] < distance[cur][power + 1]) {distance[cur][power + 1] = cost + charge[cur];heap.add(new int[] { cur, power + 1, cost + charge[cur] });}}for (int[] edge : graph.get(cur)) {// 不充电去别的城市int nextCity = edge[0];int restPower = power - edge[1];int nextCost = cost + edge[1];if (restPower >= 0 && !visited[nextCity][restPower] && nextCost < distance[nextCity][restPower]) {distance[nextCity][restPower] = nextCost;heap.add(new int[] { nextCity, restPower, nextCost });}}}return -1;}}

code6 P4568 [JLOI2011] 飞行路线

// 飞行路线(语言提供的堆)
// Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司
// 该航空公司一共在n个城市设有业务,设这些城市分别标记为0 ~ n−1
// 一共有m种航线,每种航线连接两个城市,并且航线有一定的价格
// Alice 和 Bob 现在要从一个城市沿着航线到达另一个城市,途中可以进行转机
// 航空公司对他们这次旅行也推出优惠,他们可以免费在最多k种航线上搭乘飞机
// 那么 Alice 和 Bob 这次出行最少花费多少
// 测试链接 : https://www.luogu.com.cn/problem/P4568
// 请同学们务必参考如下代码中关于输入、输出的处理
// 这是输入输出处理效率很高的写法
// 提交以下所有代码,把主类名改成Main,可以直接通过

code6 P4568 [JLOI2011] 飞行路线

// 飞行路线(自己手撸的堆)
// Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司
// 该航空公司一共在n个城市设有业务,设这些城市分别标记为0 ~ n−1
// 一共有m种航线,每种航线连接两个城市,并且航线有一定的价格
// Alice 和 Bob 现在要从一个城市沿着航线到达另一个城市,途中可以进行转机
// 航空公司对他们这次旅行也推出优惠,他们可以免费在最多k种航线上搭乘飞机
// 那么 Alice 和 Bob 这次出行最少花费多少
// 测试链接 : https://www.luogu.com.cn/problem/P4568
// 请同学们务必参考如下代码中关于输入、输出的处理
// 这是输入输出处理效率很高的写法
// 提交以下所有代码,把主类名改成Main,可以直接通过

package class064;// 飞行路线(自己手撸的堆)
// Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司
// 该航空公司一共在n个城市设有业务,设这些城市分别标记为0 ~ n−1
// 一共有m种航线,每种航线连接两个城市,并且航线有一定的价格
// Alice 和 Bob 现在要从一个城市沿着航线到达另一个城市,途中可以进行转机
// 航空公司对他们这次旅行也推出优惠,他们可以免费在最多k种航线上搭乘飞机
// 那么 Alice 和 Bob 这次出行最少花费多少
// 测试链接 : https://www.luogu.com.cn/problem/P4568
// 请同学们务必参考如下代码中关于输入、输出的处理
// 这是输入输出处理效率很高的写法
// 提交以下所有代码,把主类名改成Main,可以直接通过import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;public class Code06_FlightPath2 {public static int MAXN = 10001;public static int MAXM = 100001;public static int MAXK = 11;// 链式前向星建图需要public static int[] head = new int[MAXN];public static int[] next = new int[MAXM];public static int[] to = new int[MAXM];public static int[] weight = new int[MAXM];public static int cnt;// Dijkstra需要public static int[][] distance = new int[MAXN][MAXK];public static boolean[][] visited = new boolean[MAXN][MAXK];// 自己写的普通堆,静态结构,推荐// 注意是自己写的普通堆,不是反向索引堆// 因为(点编号,使用免费路线的次数),两个参数的组合才是图中的点// 两个参数的组合对应一个点(一个堆的下标),所以反向索引堆不好写// 其实也能实现,二维点变成一维下标即可// 但是会造成很多困惑,索性算了,就手写普通堆吧public static int[][] heap = new int[MAXM * MAXK][3];public static int heapSize;public static int n, m, k, s, t;public static void build() {cnt = 1;heapSize = 0;for (int i = 0; i < n; i++) {head[i] = 0;for (int j = 0; j <= k; j++) {distance[i][j] = Integer.MAX_VALUE;visited[i][j] = false;}}}public static void addEdge(int u, int v, int w) {next[cnt] = head[u];to[cnt] = v;weight[cnt] = w;head[u] = cnt++;}public static void push(int u, int t, int c) {heap[heapSize][0] = u;heap[heapSize][1] = t;heap[heapSize][2] = c;int i = heapSize++;while (heap[i][2] < heap[(i - 1) / 2][2]) {swap(i, (i - 1) / 2);i = (i - 1) / 2;}}public static int u, use, cost;public static void pop() {u = heap[0][0];use = heap[0][1];cost = heap[0][2];swap(0, --heapSize);heapify();}public static void heapify() {int i = 0;int l = 1;while (l < heapSize) {int best = l + 1 < heapSize && heap[l + 1][2] < heap[l][2] ? l + 1 : l;best = heap[best][2] < heap[i][2] ? best : i;if (best == i) {break;}swap(best, i);i = best;l = i * 2 + 1;}}public static void swap(int i, int j) {int[] tmp = heap[i];heap[i] = heap[j];heap[j] = tmp;}public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));StreamTokenizer in = new StreamTokenizer(br);PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));while (in.nextToken() != StreamTokenizer.TT_EOF) {n = (int) in.nval;in.nextToken(); m = (int) in.nval;in.nextToken(); k = (int) in.nval;in.nextToken(); s = (int) in.nval;in.nextToken(); t = (int) in.nval;build();for (int i = 0, a, b, c; i < m; i++) {in.nextToken(); a = (int) in.nval;in.nextToken(); b = (int) in.nval;in.nextToken(); c = (int) in.nval;addEdge(a, b, c);addEdge(b, a, c);}out.println(dijkstra());}out.flush();out.close();br.close();}public static int dijkstra() {distance[s][0] = 0;push(s, 0, 0);while (heapSize > 0) {pop();if (visited[u][use]) {continue;}visited[u][use] = true;if (u == t) {// 常见剪枝// 发现终点直接返回// 不用等都结束return cost;}for (int ei = head[u], v, w; ei > 0; ei = next[ei]) {v = to[ei];w = weight[ei];if (use < k && distance[v][use + 1] > distance[u][use]) {// 使用免费distance[v][use + 1] = distance[u][use];push(v, use + 1, distance[v][use + 1]);}if (distance[v][use] > distance[u][use] + w) {// 不用免费distance[v][use] = distance[u][use] + w;push(v, use, distance[v][use]);}}}return -1;}}

2023-12-9 19:21:42

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/211683.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

法律服务网站建设效果如何

律师事务所及法律知识咨询机构等往往是众多人群需求的服务&#xff0c;服务多样化及内容多元化&#xff0c;市场中也有大量品牌&#xff0c;在实际消费服务中大多以本地事务所为主&#xff0c;而线上咨询服务则一般没有区域限制&#xff0c;同行增多及人们知识获取渠道增加&…

C++-引用和指针区别

文章目录 1.变量的组成2.指针2.1 定义2.2 使用指针操作变量2.3 为什么使用指针 3.引用3.1 定义3.2 引用注意事项 4.引用和指针的区别 1.变量的组成 变量的组成&#xff1a;变量地址&#xff0c;变量名&#xff0c;变量值 例&#xff1a; int i 12;2.指针 2.1 定义 指针用于存…

如何为游戏角色3D模型设置纹理贴图

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 当谈到游戏角色的3D模型风格时&#xff0c;有几种不同的风格&#xf…

Mybatis中的查询操作

单表查询 单表查询在《初始Mybatis》中已经介绍过&#xff0c;这里就不在介绍了。咱们这里只说单表查询中的“like查询”。like查询单独使用#{}报错 <select id"selectByKeyword" resultType"com.example.demo.entity.Userinfo">select * from use…

计网Lesson8 - NAT技术与链路层概述

文章目录 NAT 技术1. 因特网的接入方式2. 公网和私网3. NAT 技术 链路层1. 数据链路层概述2. 数据链路层的三个问题2.1 封装成帧2.2 透明传输2.3 差错检测 NAT 技术 1. 因特网的接入方式 光猫将电信号转换为数字信号发送给路由器 光纤入户 光纤传递的就是数字信号&#xff0c…

python+pytest接口自动化(12)-自动化用例编写思路 (使用pytest编写一个测试脚本)

经过之前的学习铺垫&#xff0c;我们尝试着利用pytest框架编写一条接口自动化测试用例&#xff0c;来厘清接口自动化用例编写的思路。 我们在百度搜索天气查询&#xff0c;会出现如下图所示结果&#xff1a; 接下来&#xff0c;我们以该天气查询接口为例&#xff0c;编写接口测…

每日一练2023.12.9—— 矩阵A乘以B【PTA】

题目链接&#xff1a;L1-048 矩阵A乘以B 题目要求&#xff1a; 给定两个矩阵A和B&#xff0c;要求你计算它们的乘积矩阵AB。需要注意的是&#xff0c;只有规模匹配的矩阵才可以相乘。即若A有Ra​行、Ca​列&#xff0c;B有Rb​行、Cb​列&#xff0c;则只有Ca​与Rb​相等时&a…

Linux Shell 基础命令

Linux 是一个开源的操作系统&#xff0c;其命令行界面是它的重要组成部分。在这个界面下&#xff0c;Shell 是一个能够与操作系统进行交互的工具。Shell 是一种程序&#xff0c;它能够接收用户输入的命令&#xff0c;并将这些命令发送到操作系统中进行处理。 在 Linux 中&…

VINS-MONO代码解读5----vins_estimator(marginalization部分)

文章目录 0. 前言1.1 Marginalization Pipiline 1. marg factor构建1.1 变量及维度理解1.2 IMUFactor1.3 ProjectionTdFactor(ProjectionFactor)1.4 MarginalizationFactor( e p e_p ep​推导更新&#xff0c;FEJ解决的问题)1.4.1 先验残差的更新1.4.2 先验Jacobian的更新 2. R…

windows install git

refer: https://developers.weixin.qq.com/miniprogram/dev/devtools/wechatvcs.html https://blog.csdn.net/weixin_40228200/article/details/128451324 在使用小程序的时候&#xff0c;需要初始化项目&#xff0c;需要注册Git账号 1.在本地确认cmd没有安装Git,进入Git官网…

docker:安装mysql以及最佳实践

文章目录 1、拉取镜像2、运行容器3、进入容器方式一方式二方式三容器进入后连接mysql和在宿主机连接mysql的区别 持久化数据持久化数据最佳实践 1、拉取镜像 docker pull mysql2、运行容器 docker run -d -p 3307:3306 --name mysql-container -e MYSQL_ROOT_PASSWORD123456 …

Botton进一步了解(点击事件)

点击事件和长按事件 监听器&#xff1a;专门监听控件的动作行为。只有控件发生了指定的动作&#xff0c;监听器才会触发开关区执行对应的代码逻辑。按钮控件有两种常用的监听器&#xff1a; 点击监听器&#xff1a;通过setOnClickListener方法设置。按钮被按住少于500ms时会触…

2023济南大学acm新生赛题解

通过答题情况的难度系数&#xff1a; 签到&#xff1a;ACI 铜牌题&#xff1a;BG 银牌题&#xff1a;EF 金牌题&#xff1a;DHJKO 赛中暂未有人通过&#xff1a;LMNP A - AB Problem 直接根据公式计算就行。 #include<stdio.h> int main(){int a,b;scanf("%…

安卓MediaRecorder(2)录制源码分析

文章目录 前言JAVA new MediaRecorder() 源码分析android_media_MediaRecorder.cpp native_init()MediaRecorder.java postEventFromNativeandroid_media_MediaRecorder.cpp native_setup() MediaRecorder 参数设置MediaRecorder.prepare 分析MediaRecorder.start 分析MediaRec…

【Angular开发】Angular在2023年之前不是很好

做一个简单介绍&#xff0c;年近48 &#xff0c;有20多年IT工作经历&#xff0c;目前在一家500强做企业架构&#xff0e;因为工作需要&#xff0c;另外也因为兴趣涉猎比较广&#xff0c;为了自己学习建立了三个博客&#xff0c;分别是【全球IT瞭望】&#xff0c;【架构师酒馆】…

SSL证书更新

首先&#xff0c;我们需要理解为什么需要更新SSL证书。SSL证书的有效期通常为一年。一旦证书过期&#xff0c;浏览器会显示警告&#xff0c;提示用户该网站的SSL证书已经过期&#xff0c;这可能会导致用户对网站的信任度下降&#xff0c;甚至直接离开网站。此外&#xff0c;一些…

【Python】手把手教你用tkinter设计图书管理登录UI界面(一)

下一篇&#xff1a; 本项目将分段设计“图书管理登录UI界面”的用户登录、用户注册、用户账号找回等。主要围绕GUI标准库tkinter、以及类的继承&#xff08;重点&#xff09;来设计本项目。 首先新建一个文件夹命名为“图书管理系统项目”&#xff0c;并在其目录下新建文件夹…

【分治】最接近点对Python实现

文章目录 [toc]问题描述一维最接近点对算法Python实现 二维最接近点对算法分治算法时间复杂性Python实现 问题描述 给定平面上 n n n个点&#xff0c;找其中的一对点&#xff0c;使得在 n n n个点组成的所有点对中&#xff0c;该点对的距离最小 一维最接近点对算法 Python实…

LED透镜粘接UV胶是一种特殊的UV固化胶,用于固定和粘合LED透镜。

LED透镜粘接UV胶是一种特殊的UV固化胶&#xff0c;用于固定和粘合LED透镜。 它具有以下特点&#xff1a; 1. 高透明度&#xff1a;LED透镜粘接UV胶具有高透明度&#xff0c;可以确保光线的透过性&#xff0c;不影响LED的亮度和效果。 2. 快速固化&#xff1a;经过UV紫外线照射…

CPU、MCU、MPU、DSP、FPGA各是什么?有什么区别?

1、CPU 中央处理器&#xff0c;简称 CPU&#xff08;Central Processing Unit&#xff09;&#xff0c;中央处理器主要包括两个部分&#xff0c;即控制器、运算器&#xff0c;其中还包括高速缓冲存储器及实现它们之间联系的数据、控制的总线。 电子计算机三大核心部件就是CPU…