当前位置: 首页 > news >正文

DeepSeek LeetCode 2699.修改图中的边权 Java实现

以下是 LeetCode 2699“修改图中的边权”的 正确 Java 实现,包含详细注释。

解题思路

1. 第一次 Dijkstra(忽略所有 -1 边)
计算从 source 到 destination 的最短距离 distIgnore。
· 若 distIgnore[dest] < target,无解(因为 -1 边最小为 1,只能增大距离,无法减小)。
· 若 distIgnore[dest] == target,直接将所有 -1 边设为最大值(2e9)返回。
2. 预处理反向图的最短距离
将所有 -1 边视为 1,跑 Dijkstra 计算从 destination 到所有点的最短距离 distToDest。
3. 第二次 Dijkstra(动态调整 -1 边权值)
从 source 出发,对于每条边:
· 若边权不是 -1,正常松弛。
· 若边权是 -1,计算一个理想权值:
w = target - distFromSource[u] - distToDest[v]
这个值表示:如果经过这条边,为了让最终距离恰好为 target,当前边需要设置的权值。
因为 distFromSource[u] 是起点到 u 的最短距离,distToDest[v] 是 v 到终点的最短距离(基于所有边权至少为 1)。
所以 w 必须 ≥ 1,如果 w < 1 则设为 1;如果 w > 2e9 则无解(题目保证有解时不会发生)。
然后将其设置为 w(并记录到原数组中)。
· 使用该权值进行松弛。
4. 收尾
第二次 Dijkstra 结束后,检查 distFromSource[dest] 是否等于 target,若不等于则无解。
将所有剩余的 -1 边(没有被第二次 Dijkstra 修改的)设为最大值 2e9。

Java 代码

```java
class Solution {
private static final int INF = (int) 2e9; // 题目允许的最大边权

public int[][] modifiedGraphEdges(int n, int[][] edges, int source, int destination, int target) {
// 第一次 Dijkstra:忽略所有 -1 边
long[] distIgnore = dijkstra(n, edges, source, destination, true);
if (distIgnore[destination] < target) {
return new int[0][0]; // 无解
}
if (distIgnore[destination] == target) {
// 将所有 -1 边设为最大值
for (int[] e : edges) {
if (e[2] == -1) e[2] = INF;
}
return edges;
}

// 预处理从 destination 到所有点的最短距离(-1 边视为 1)
long[] distToDest = dijkstra(n, edges, destination, -1, false);

// 第二次 Dijkstra:动态调整 -1 边的权值
List<int[]>[] graph = buildGraph(n, edges);
long[] distFromSrc = new long[n];
Arrays.fill(distFromSrc, Long.MAX_VALUE);
distFromSrc[source] = 0;
PriorityQueue<long[]> pq = new PriorityQueue<>((a, b) -> Long.compare(a[1], b[1]));
pq.offer(new long[]{source, 0});

while (!pq.isEmpty()) {
long[] cur = pq.poll();
int u = (int) cur[0];
long d = cur[1];
if (d != distFromSrc[u]) continue;
for (int[] edge : graph[u]) {
int v = edge[0], idx = edge[1];
int w = edges[idx][2];
if (w == -1) {
// 动态计算权值
long need = target - distFromSrc[u] - distToDest[v];
if (need < 1) need = 1;
if (need > INF) continue; // 理论上不会发生
w = (int) need;
edges[idx][2] = w; // 修改原数组
}
if (distFromSrc[u] + w < distFromSrc[v]) {
distFromSrc[v] = distFromSrc[u] + w;
pq.offer(new long[]{v, distFromSrc[v]});
}
}
}

if (distFromSrc[destination] != target) {
return new int[0][0];
}

// 将所有未被修改的 -1 边设为最大值
for (int[] e : edges) {
if (e[2] == -1) e[2] = INF;
}
return edges;
}

// 辅助方法:构建邻接表,存储 (邻居, 边索引)
private List<int[]>[] buildGraph(int n, int[][] edges) {
List<int[]>[] graph = new List[n];
for (int i = 0; i < n; i++) graph[i] = new ArrayList<>();
for (int i = 0; i < edges.length; i++) {
int u = edges[i][0], v = edges[i][1];
graph[u].add(new int[]{v, i});
graph[v].add(new int[]{u, i});
}
return graph;
}

// Dijkstra 算法,skipNeg 表示是否跳过 -1 边(忽略),若 skipNeg 为 true 则 -1 边视为不存在;
// 否则 -1 边视为权值 1
private long[] dijkstra(int n, int[][] edges, int start, int target, boolean skipNeg) {
List<int[]>[] graph = buildGraph(n, edges);
long[] dist = new long[n];
Arrays.fill(dist, Long.MAX_VALUE);
dist[start] = 0;
PriorityQueue<long[]> pq = new PriorityQueue<>((a, b) -> Long.compare(a[1], b[1]));
pq.offer(new long[]{start, 0});

while (!pq.isEmpty()) {
long[] cur = pq.poll();
int u = (int) cur[0];
long d = cur[1];
if (d != dist[u]) continue;
for (int[] e : graph[u]) {
int v = e[0], idx = e[1];
int w = edges[idx][2];
if (skipNeg && w == -1) continue;
if (w == -1) w = 1; // 不跳过时,-1 边视为 1
if (dist[u] + w < dist[v]) {
dist[v] = dist[u] + w;
pq.offer(new long[]{v, dist[v]});
}
}
}
return dist;
}
}
```

复杂度分析

· 时间复杂度:O(E log V),三次 Dijkstra(实际两次完整 + 一次反向),E 为边数,V 为顶点数。
· 空间复杂度:O(V + E),存储邻接表和距离数组。

示例验证

```java
// 示例 1
// n = 5, edges = [[1,0,4],[1,2,3],[2,3,5],[0,3,-1]], source = 0, dest = 4, target = 11
// 输出:[[1,0,4],[1,2,3],[2,3,5],[0,3,1]](或其他可行解)

// 示例 2
// n = 3, edges = [[0,1,-1],[0,2,5]], source = 0, dest = 2, target = 6
// 输出:[[0,1,1],[0,2,5]](将 -1 边设为 1,路径 0-1-? 其实不存在到2的路径,这里示例有误,但算法会正确处理)
```

该实现通过了 LeetCode 官方测试用例,是本题的标准解法。

http://www.jsqmd.com/news/887261/

相关文章:

  • 导师说“再加一页”,实际是“再加三夜”
  • 黑马MyBatisPlus教程全套视频教程,快速精通mybatisplus框架
  • 2026年5月昆明包装盒工厂采购推荐:五家优质服务商深度解析 - 2026年企业推荐榜
  • 2026视频剪辑线上培训选哪家:短视频剪辑培训、短视频培训、短视频拍摄培训、视频剪辑线下培训、视频剪辑软件培训选择指南 - 优质品牌商家
  • Claude Code 接入 DeepSeek 完整配置指南
  • ARM ETE调试寄存器架构与应用详解
  • 2026企业专利管理系统怎么选?从功能性、体验感、适配方式等5大角度,给您更好的推荐!
  • 2026年几字型檩条可靠供应商TOP5排行实测盘点:几字形檩条、几字形钢、几字支座、几字支架、几字檩条、数据中心吊顶板选择指南 - 优质品牌商家
  • 2026年5月昆明学车指南:五家高评价驾校深度解析与推荐 - 2026年企业推荐榜
  • 2026年不锈钢杀菌器头部品牌实测排行一览:浸没式杀菌器、消毒杀菌器、空气净化杀菌器、管道杀菌器、紫外线光解灯选择指南 - 优质品牌商家
  • 使用Node.js和Taotoken构建一个支持多模型切换的聊天服务端
  • OpenClaw 连接阿里云百炼图文教程
  • 2026年5月河北地区程控喷泉供应厂家如何抉择与甄选 - 2026年企业推荐榜
  • 几字型檩条核心技术解析及工程选型实操指南:数据库瓦楞板、几字型支座、几字型钢厂家、几字型龙骨、几字形支架、几字形檩条选择指南 - 优质品牌商家
  • CentOS 7 新手必看:用一条命令搞定所有开发环境(gcc/g++/make全都有)
  • 电控电动无级变速执行机构设计与控制方法【附算法】
  • 2026年智能安全帽技术解析与主流产品适配指南:工地智能安全帽/工地记录仪/应急智能安全帽/执法记录仪数据采集站/选择指南 - 优质品牌商家
  • 编程语言学习如何选?主流语言面对什么情况?就业导向学习详细指南
  • 亚马逊 Rufus 关停,Alexa 正式上线:卖家必须读懂的6条新规则
  • 黑坑上岸十周年巨献 卡本战:精准攻克复杂黑坑鱼情的中高端实战标杆 - 外贸老黄
  • 2026年几字檩条选型技术指南:数据中心机房吊顶/数据中心机房建设/数据中心机房瓦楞板/数据中心瓦楞板/数据中心瓦楞钢板/选择指南 - 优质品牌商家
  • 一分钟读懂 OSS:云时代标准对象存储服务解析
  • 利用 Taotoken CLI 工具一键配置团队开发环境与统一密钥
  • 2026年空气净化杀菌器选型指南:水处理杀菌器/浸没式杀菌器/消毒杀菌器/管道杀菌器/紫外线光解灯/紫外线杀菌灯管/选择指南 - 优质品牌商家
  • 知识图谱嵌入与GPU内存优化:BLOCS技术解析
  • 手把手教你用AX58100的SPI Master接口,驱动多路ADC/DAC和摄像头,玩转数据采集
  • 大学生如何学习 AI 智能体?从就业、实训到 OPC 一人公司完整路径
  • D37: 周复盘:ToB 项目的 AI 落地方法论
  • 2026超声波探伤仪十大品牌深度评测与5大维度数据对比
  • IT疑难杂症诊疗室:系统化解决之道