Starting with an undirected graph (the "original graph") with nodes from 0
to N-1
, subdivisions are made to some of the edges.
The graph is given as follows: edges[k]
is a list of integer pairs (i, j, n)
such that (i, j)
is an edge of the original graph,
and n
is the total number of new nodes on that edge.
Then, the edge (i, j)
is deleted from the original graph, n
new nodes (x_1, x_2, ..., x_n)
are added to the original graph,
and n+1
new edges (i, x_1), (x_1, x_2), (x_2, x_3), ..., (x_{n-1}, x_n), (x_n, j)
are added to the original graph.
Now, you start at node 0
from the original graph, and in each move, you travel along one edge.
Return how many nodes you can reach in at most M
moves.
Example 1:
Input: edges
= [[0,1,10],[0,2,1],[1,2,2]], M = 6, N = 3
Output: 13
Explanation:
The nodes that are reachable in the final graph after M = 6 moves are indicated below.
Example 2:
Input: edges
= [[0,1,4],[1,2,6],[0,2,8],[1,3,1]], M = 10, N = 4
Output: 23
Note:
0 <= edges.length <= 10000
0 <= edges[i][0] < edges[i][1] < N
- There does not exist any
i != j
for whichedges[i][0] == edges[j][0]
andedges[i][1] == edges[j][1]
. - The original graph has no parallel edges.
0 <= edges[i][2] <= 10000
0 <= M <= 10^9
1 <= N <= 3000
- A reachable node is a node that can be travelled to using at most M moves starting from node 0.
题目理解:
给定一个无向图,从0节点开始可以走M步,问最多能访问多少个节点。注意这个图的一部分边被划分了,也就是向边中添加了若干个子节点。
解题思路:
找到每一个原始节点能够走的最长步数,然后按照这个最大步数访问它周围的子节点。为了避免重复,所有访问过的节点的数目都从子节点数目中减掉。最后加上所有能够访问的原始节点数目。
找到每一个原始节点能够走的最大步数可以使用广度优先搜索BFS,这里的搜索条件是某一个原始节点的最大步数有变化。
为了降低复杂度,使用一个字典存储每一个原始节点直接连通的节点。
代码如下:
class Solution {
public int reachableNodes(int[][] edges, int M, int N) {
Queue<Integer> qu = new LinkedList<Integer>();
Set<Integer> visited = new HashSet<Integer>();
Map<Integer, Set<Integer>> map = new HashMap<Integer, Set<Integer>>();
int res = 0;
int[][] graph = new int[N][N];
int[] max = new int[N];
qu.offer(0);
max[0] = M;
for(int[] it : graph) {
Arrays.fill(it, -1);
}
for(int[] it : edges) {
graph[it[0]][it[1]] = it[2];
graph[it[1]][it[0]] = it[2];
if(!map.containsKey(it[0]))
map.put(it[0], new HashSet<Integer>());
if(!map.containsKey(it[1]))
map.put(it[1], new HashSet<Integer>());
map.get(it[0]).add(it[1]);
map.get(it[1]).add(it[0]);
}
while(!qu.isEmpty()) {
int start = qu.poll();
for(int end : map.getOrDefault(start, new HashSet<Integer>())) {
if(graph[start][end] == -1 || start == end)
continue;
int remain = max[start] - Math.min(max[start], graph[start][end] + 1);
if(remain > max[end]) {//continue to visit other nodes
qu.offer(end);
max[end] = remain;
}
}
}
for(int i = 0; i < N; i++) {
int dis = max[i];
if(dis > 0) {
visited.add(i);
for(int j : map.getOrDefault(i, new HashSet<Integer>())) {
if(graph[i][j] < 0)
continue;
if(dis > graph[i][j])
visited.add(j);
res += Math.min(dis, graph[i][j]);
int temp = Math.max(0, graph[i][j] - dis);
graph[i][j] = temp;
graph[j][i] = temp;
}
}
}
return res + visited.size();
}
}