但当每条边上都加入细分节点后,需要考虑细分节点是否可达。用一个哈希表 used 记录各条边上的细分节点的可达情况,键为二元点对 (u,v) 表示从点 u 到点 v 的边,值为这条边上的可达细分节点数。注意在计算细分节点时,是考虑单向的情况,即会分别计算 used}[(u, v)] 和 used}[(v, u)],并且这两个值不一定相等。计算 used 时,是要在访问路径最短的节点 u 的邻接节点 v 时计算。如果邻接节点的路径长度小于等于 maxMoves,说明这条边上的细分节点都可达,否则只有一部分可达,且这部分细分节点是靠近节点 u 的。
计算总的可达节点时,需要加上细分节点的部分。但每条边上的细分节点可能会被计算过两次,即 used}[(u, v) 和 used}[(v, u)],他们分别是是靠近 u 开始计算的和靠近 v 开始计算的,需要对这两部分进行去重。
classSolution: defreachableNodes(self, edges: List[List[int]], maxMoves: int, n: int) -> int: adList = defaultdict(list) for u, v, nodes in edges: adList[u].append([v, nodes]) adList[v].append([u, nodes]) used = {} visited = set() reachableNodes = 0 pq = [[0, 0]]
while pq and pq[0][0] <= maxMoves: step, u = heapq.heappop(pq) if u in visited: continue visited.add(u) reachableNodes += 1 for v, nodes in adList[u]: if nodes + step + 1 <= maxMoves and v notin visited: heappush(pq, [nodes + step + 1, v]) used[(u, v)] = min(nodes, maxMoves - step)
for u, v, nodes in edges: reachableNodes += min(nodes, used.get((u, v), 0) + used.get((v, u), 0)) return reachableNodes
publicclassSolution { publicintReachableNodes(int[][] edges, int maxMoves, int n) { IList<int[]>[] adList = new IList<int[]>[n]; for (int i = 0; i < n; i++) { adList[i] = new List<int[]>(); } foreach (int[] edge in edges) { int u = edge[0], v = edge[1], nodes = edge[2]; adList[u].Add(newint[]{v, nodes}); adList[v].Add(newint[]{u, nodes}); } IDictionary<int, int> used = new Dictionary<int, int>(); ISet<int> visited = new HashSet<int>(); int reachableNodes = 0; PriorityQueue<int[], int> pq = new PriorityQueue<int[], int>(); pq.Enqueue(newint[]{0, 0}, 0);
while (pq.Count > 0 && pq.Peek()[0] <= maxMoves) { int[] pair = pq.Dequeue(); int step = pair[0], u = pair[1]; if (!visited.Add(u)) { continue; } reachableNodes++; foreach (int[] next in adList[u]) { int v = next[0], nodes = next[1]; if (nodes + step + 1 <= maxMoves && !visited.Contains(v)) { pq.Enqueue(newint[]{nodes + step + 1, v}, nodes + step + 1); } used.Add(Encode(u, v, n), Math.Min(nodes, maxMoves - step)); } }
foreach (int[] edge in edges) { int u = edge[0], v = edge[1], nodes = edge[2]; int key1 = Encode(u, v, n), key2 = Encode(v, u, n); reachableNodes += Math.Min(nodes, (used.ContainsKey(key1) ? used[key1] : 0) + (used.ContainsKey(key2) ? used[key2] : 0)); } return reachableNodes; }
publicintEncode(int u, int v, int n) { return u * n + v; } }
classSolution { public: intencode(int u, int v, int n){ return u * n + v; }
intreachableNodes(vector<vector<int>>& edges, int maxMoves, int n){ vector<vector<pair<int, int>>> adList(n); for (auto &edge : edges) { int u = edge[0], v = edge[1], nodes = edge[2]; adList[u].emplace_back(v, nodes); adList[v].emplace_back(u, nodes); }