![](/img/trans.png)
[英]Finding shortest path between two nodes in a weighted DAG with negative weights
[英]Finding shortest path between two nodes
我试图弄清楚如何制作一种在两个节点之间找到最短路径的方法,但似乎无法弄清楚。 我得到了两个文件,一个包含演员(将是节点)的文件和一个包含电影(将是边缘)的文件。
我将一个图表表示为一个 HashMap,其中键是一个演员,而值是一个 ArrayList,其中包含该演员出演过的电影:
HashMap<Actor, ArrayList[Movie]> graph;
现在我想找到两个演员之间的最短路径,但我不知道该怎么做。 我在考虑 DFS 或 BFS,但我不太确定如何使用这个哈希图来做到这一点..
您可以使用您当前的结构( HashMap<Actor, ArrayList<Movie>>
)作为邻接列表,但缺少一些东西:一种从电影回到主演的有效方法。 您可以构建一个Map<Movie, List<Actor>>
,这会起作用……但使用单个邻接列表更简单,而不是让一个用于演员而另一个用于电影。 我会这样做(假设Actor
和Movie
都实现了equals
和hashcode
,并且没有演员等于任何电影):
Map<Object, List<Object>> edges = new HashMap<>();
for (Map.Entry<Actor, ArrayList<Movie>> e : graph.entries()) {
Actor a = e.getKey();
edges.put(a, new ArrayList<Object>(e.getValues()));
for (Movie m : e.getValues()) {
List<Actor> otherActors = edges.getOrDefault(m, new ArrayList<Object>());
otherActors.add(a);
edges.put(m, otherActors);
}
}
现在您可以使用edges
来执行标准的广度优先搜索。 保证为您提供任意 2 个演员之间的最短路径(可能有多个同样短的路径),并且该路径将包含链接他们的电影。
仅仅为您指明方向并不是整个解决方案,您必须按照tucuxi 建议创建一个 Map<Movie, List> 。 您一个一个地遍历每个角色并标记当前角色与参考角色的距离。
private static void fn(HashMap<Actor, List<Movie>> graph, Actor referenceActor) {
var movieMap = new HashMap<Movie, List<Actor>>();
graph.forEach((key, value) -> {
for (var movie : value) {
movieMap.compute(movie, (k, v) -> {
if (v == null) {
return new ArrayList<>(List.of(key));
}
v.add(key);
return v;
});
}
});
final var visited = new HashSet<Actor>();
var dq = new ArrayDeque<Actor>();
var map = new HashMap<Actor, Integer>();
dq.add(referenceActor);
int distance = 0;
while (!dq.isEmpty()) {
var size = dq.size();
for (int i = 0; i < size; i++) {
var actor = dq.poll();
visited.add(actor);
map.putIfAbsent(actor, distance);
for (Movie movie : graph.get(actor)) {
// adding every non visited actor in the same movie in the queue
dq.addAll(movieMap
.get(movie)
.stream()
.filter(x -> !visited.contains(x))
.collect(Collectors.toList()));
}
}
distance++;
}
System.out.println(map);
}
我在这里使用ArrayDeque
以 BFS 方式遍历,如果您希望 DFS 记住,计算距离的逻辑也需要更改,您可以修改。 从评论中粘贴图像,将节点 B 作为参考参与者。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.