Reachable Nodes In Subdivided Graph
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)
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();
}
}