There are n
cities numbered from 0
to n-1
. Given the array edges
where edges[i] = [fromi, toi, weighti]
represents a bidirectional and weighted edge between cities fromi
and toi
, and given the integer distanceThreshold
.
Return the city with the smallest number of cities that are reachable through some path and whose distance is at most distanceThreshold
, If there are multiple such cities, return the city with the greatest number.
Notice that the distance of a path connecting cities i and j is equal to the sum of the edges' weights along that path.
Example 1:
Input: n = 4, edges = [[0,1,3],[1,2,1],[1,3,4],[2,3,1]], distanceThreshold = 4
Output: 3
Explanation: The figure above describes the graph.
The neighboring cities at a distanceThreshold = 4 for each city are:
City 0 -> [City 1, City 2]
City 1 -> [City 0, City 2, City 3]
City 2 -> [City 0, City 1, City 3]
City 3 -> [City 1, City 2]
Cities 0 and 3 have 2 neighboring cities at a distanceThreshold = 4, but we have to return city 3 since it has the greatest number.
思路:dijkstra algorithm,tricky的地方还是visited不能直接加入visited,要用pop的来判断;否则失去最优解; 对于1个node是ElogV, 那么所有node就是VElogV, 由于E ~ V2, 那么这题就是V3logV.
Key point:
1. graph ->HashMap<Integer, List<Node>>;
2. 每个点,作为起点,cost是distanceThreshold开始往外走;走一步,下一node cost减去weight,加入pq,这样每次都是走最大的cost,这样得到的node数目最小;
class Solution {
private class Node {
public int city;
public int cost;
public Node (int city, int cost) {
this.city = city;
this.cost = cost;
}
}
public int findTheCity(int n, int[][] edges, int distanceThreshold) {
if(edges == null || edges.length == 0 || edges[0].length == 0) {
return -1;
}
HashMap<Integer, List<Node>> graph = new HashMap<>();
for(int[] edge: edges) {
int from = edge[0];
int to = edge[1];
int weight = edge[2];
graph.putIfAbsent(from, new ArrayList<Node>());
graph.putIfAbsent(to, new ArrayList<Node>());
graph.get(from).add(new Node(to, weight));
graph.get(to).add(new Node(from, weight));
}
int maxnode = -1;
int minsize = n;
for(int i = 0; i < n; i++) {
PriorityQueue<Node> pq = new PriorityQueue<Node>((a, b) -> {
if(a.cost != b.cost) {
return b.cost - a.cost;
} else {
return b.city - a.city;
}
});
pq.offer(new Node(i, distanceThreshold));
HashSet<Integer> visited = new HashSet<>();
int count = 0;
while(!pq.isEmpty()) {
Node node = pq.poll();
if(visited.contains(node.city)) {
continue;
}
visited.add(node.city);
count++;
if(graph.containsKey(node.city)) {
for(Node neighbor: graph.get(node.city)) {
if(!visited.contains(neighbor.city )){
if(node.cost - neighbor.cost >= 0) {
pq.offer(new Node(neighbor.city, node.cost - neighbor.cost));
}
}
}
}
}
if(count <= minsize) {
minsize = count;
maxnode = i;
}
}
return maxnode;
}
}
思路2 用floyd-warshall算法 dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]); time complexity: O(V^3)
class Solution {
public int findTheCity(int n, int[][] edges, int distanceThreshold) {
int[][] dis = new int[n][n];
int res = 0;
int smallcount = n;
for(int[] row: dis) {
Arrays.fill(row, 10000);
}
for(int[] e: edges) {
dis[e[0]][e[1]] = dis[e[1]][e[0]] = e[2];
}
for(int i = 0; i < n; i++) {
dis[i][i] = 0;
}
for(int k = 0; k < n; k++) {
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
dis[i][j] = Math.min(dis[i][j], dis[i][k] + dis[k][j]);
}
}
}
for(int i = 0; i < n; i++) {
int count = 0;
for(int j = 0; j < n; j++) {
if(dis[i][j] <= distanceThreshold) {
count++;
}
}
if(count <= smallcount) {
smallcount = count;
res = i;
}
}
return res;
}
}