Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[pull] master from youngyangyang04:master #511

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
pull merged 6 commits into AlgorithmAndLeetCode:master from youngyangyang04:master
Dec 15, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
docs:补充【0096-城市间货物运输III】JAVA版本的SPFA思路
补充【0096-城市间货物运输III】JAVA版本的SPFA思路
  • Loading branch information
holic-x committed Dec 12, 2024
commit 96bb3d1bfeb507859ad3fcc00bd809f913dbce7c
119 changes: 119 additions & 0 deletions problems/kamacoder/0096.城市间货物运输III.md
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,125 @@ public class Main {

```

```java
class Edge {
public int u; // 边的端点1
public int v; // 边的端点2
public int val; // 边的权值

public Edge() {
}

public Edge(int u, int v) {
this.u = u;
this.v = v;
this.val = 0;
}

public Edge(int u, int v, int val) {
this.u = u;
this.v = v;
this.val = val;
}
}

/**
* SPFA算法(版本3):处理含【负权回路】的有向图的最短路径问题
* bellman_ford(版本3) 的队列优化算法版本
* 限定起点、终点、至多途径k个节点
*/
public class SPFAForSSSP {

/**
* SPFA算法
*
* @param n 节点个数[1,n]
* @param graph 邻接表
* @param startIdx 开始节点(源点)
*/
public static int[] spfa(int n, List<List<Edge>> graph, int startIdx, int k) {
// 定义最大范围
int maxVal = Integer.MAX_VALUE;
// minDist[i] 源点到节点i的最短距离
int[] minDist = new int[n + 1]; // 有效节点编号范围:[1,n]
Arrays.fill(minDist, maxVal); // 初始化为maxVal
minDist[startIdx] = 0; // 设置源点到源点的最短路径为0

// 定义queue记录每一次松弛更新的节点
Queue<Integer> queue = new LinkedList<>();
queue.offer(startIdx); // 初始化:源点开始(queue和minDist的更新是同步的)


// SPFA算法核心:只对上一次松弛的时候更新过的节点关联的边进行松弛操作
while (k + 1 > 0 && !queue.isEmpty()) { // 限定松弛 k+1 次
int curSize = queue.size(); // 记录当前队列节点个数(上一次松弛更新的节点个数,用作分层统计)
while (curSize-- > 0) { //分层控制,限定本次松弛只针对上一次松弛更新的节点,不对新增的节点做处理
// 记录当前minDist状态,作为本次松弛的基础
int[] minDist_copy = Arrays.copyOfRange(minDist, 0, minDist.length);

// 取出节点
int cur = queue.poll();
// 获取cur节点关联的边,进行松弛操作
List<Edge> relateEdges = graph.get(cur);
for (Edge edge : relateEdges) {
int u = edge.u; // 与`cur`对照
int v = edge.v;
int weight = edge.val;
if (minDist_copy[u] + weight < minDist[v]) {
minDist[v] = minDist_copy[u] + weight; // 更新
// 队列同步更新(此处有一个针对队列的优化:就是如果已经存在于队列的元素不需要重复添加)
if (!queue.contains(v)) {
queue.offer(v); // 与minDist[i]同步更新,将本次更新的节点加入队列,用做下一个松弛的参考基础
}
}
}
}
// 当次松弛结束,次数-1
k--;
}

// 返回minDist
return minDist;
}

public static void main(String[] args) {
// 输入控制
Scanner sc = new Scanner(System.in);
System.out.println("1.输入N个节点、M条边(u v weight)");
int n = sc.nextInt();
int m = sc.nextInt();

System.out.println("2.输入M条边");
List<List<Edge>> graph = new ArrayList<>(); // 构建邻接表
for (int i = 0; i <= n; i++) {
graph.add(new ArrayList<>());
}
while (m-- > 0) {
int u = sc.nextInt();
int v = sc.nextInt();
int weight = sc.nextInt();
graph.get(u).add(new Edge(u, v, weight));
}

System.out.println("3.输入src dst k(起点、终点、至多途径k个点)");
int src = sc.nextInt();
int dst = sc.nextInt();
int k = sc.nextInt();

// 调用算法
int[] minDist = SPFAForSSSP.spfa(n, graph, src, k);
// 校验起点->终点
if (minDist[dst] == Integer.MAX_VALUE) {
System.out.println("unreachable");
} else {
System.out.println("最短路径:" + minDist[n]);
}
}
}
```



### Python
```python
def main():
Expand Down

AltStyle によって変換されたページ (->オリジナル) /