Algorithm 制作Dijkstra';返回行程时间的s算法

Algorithm 制作Dijkstra';返回行程时间的s算法,algorithm,tree,dijkstra,Algorithm,Tree,Dijkstra,所以问题是这样的:一个未加权的树提供给我,允许我从任何节点开始,我只希望访问数组中提供的某些节点。我的目标是找到到达每个节点所需的时间。每条边只需一分钟即可通过 我已经尝试实现Dijkstra的算法,以便从我想要访问的节点开始,并尝试从那里形成最短路径。 但我的问题是,虽然提供了一个解决方案,但它可能不是最有效的解决方案,因为我不知道如何强制Dijkstra的算法来解释两次在同一条边上移动。 上图就是这个问题的一个例子。假设我想要访问节点[90,50,20,75],我从节点90开始,穿过节点5

所以问题是这样的:一个未加权的树提供给我,允许我从任何节点开始,我只希望访问数组中提供的某些节点。我的目标是找到到达每个节点所需的时间。每条边只需一分钟即可通过

我已经尝试实现Dijkstra的算法,以便从我想要访问的节点开始,并尝试从那里形成最短路径。 但我的问题是,虽然提供了一个解决方案,但它可能不是最有效的解决方案,因为我不知道如何强制Dijkstra的算法来解释两次在同一条边上移动。


上图就是这个问题的一个例子。假设我想要访问节点[90,50,20,75],我从节点90开始,穿过节点50,然后穿过节点20,我如何使Dijkstra的算法在到达节点20之前计算返回到节点50的行程时间?

让我详细说明我的评论:首先,我们将修复树中的任意根,从而使树成为根(可能你已经有了一个根树)。然后,第一步是找到一个最小长度的循环,从根开始,到根结束,并通过所有需要的节点

这可以通过分而治之的方法完成。如果您在任何节点,您可以检查是否需要将该节点包括在路径中。如果需要,您可以这样做。然后,对于每个子树,只需使用相同的方法,并在必要时扩展路径。最后,确保子路径返回到当前子树的根(代码如下)

找到循环后,需要删除最长的子路径,以便最终得到一条非循环路径。这可以在线性时间内通过循环来完成。在我的实现中,我让循环提取不仅发出节点序列,还发出一个标志,用于确定路径是否只是通过节点(并且不访问节点)。因此,此步骤仅查找实际访问的任意两个节点之间的路径段

为了保证最佳性,仍然缺少一个必要的步骤。但让我向您展示到目前为止的代码。我已经用JavaScript实现了它,因为您可以在JavaScript上运行它。实现的目标是可理解性,而不是效率

//示例中的树
变量树={value:90,子项:[{value:50,子项:[{value:20,子项:[{value:5},{value:25}]},{value:75,子项:[{value:66},{value:80}]},{value:150,子项:[{value:95,子项:[{{value:92},{value:111},{value:175,子项:[{{value:166},{value:200}]};
var nodesToVisit=[90,50,20,75];
//var nodesToVisit=[92111166];
功能查找循环(树节点、节点访问){
var子路径=[];
var currentNodeIncluded=false;
if(nodesToVisit.indexOf(treeNode.value)!=-1){
//应访问此节点
push({node:treeNode,passThrough:false});
currentNodeIncluded=真;
}
//查找所有子树的子路径
if(treeNode.children){
对于(变量i=0;i0){
如果(!CurrentNode包括在内){
push({node:treeNode,passThrough:true});
currentNodeIncluded=真;
}			
//如果需要访问此子树,请将其合并到当前路径
subPath=subPath.concat(subTreePath);
push({node:treeNode,passThrough:true});//返回到当前节点
}
}
}
返回子路径;
}
函数removeLongestPassThroughSegment(循环){
var longestSegmentStart=-1;
var longestSegmentEnd=-1;
//非直通节点之间当前直通段的起点
var currentStart=-1;
var segmentLengthAtStart=-1;
对于(变量i=0;i最长分段结束-最长分段开始){
longestSegmentStart=currentStart;
longestSegmentEnd=i;
}
}否则
分段长度thatstart=i;
currentStart=i;
}
}
//检查环绕的路径段
if(cycle.length-currentStart+分段长度thatstart>最长分段结束-最长分段开始){
longestSegmentStart=currentStart;
longestSegmentEnd=开始的分段长度;
}
//通过切割最长的段来构建最终路径
var路径=[];
var i=最长分段末端;
做{
路径推送(循环[i]);
i++;
如果(i>=周期长度)
i=0;
}而(i!=最长的开始时间);
推送(循环[最长分段开始]);
返回路径;
}
函数printPath(path){
对于(变量i=0;i打印路径(路径)
树的优点是任意两个节点之间的路径都是唯一的。因此,实际上您不需要路径查找算法。顺便说一句,Dijkstra仅对加权图有意义。对于未加权图,BFS更简单,通常更快。开始和/或结束节点是固定的吗?@NicoSchertler不,先生,开始和结束节点由我决定,尽管如此我知道任何两个节点之间的路径都是唯一的,我的解决方案是考虑访问每个节点的总时间(假设它们都是商店,我是一个人,可以在我想要的任何节点开始行走,每条边需要1分钟才能走过去),我不确定我的程序应该如何知道何时返回到同一边缘?谢谢你的时间我没有完整的算法,只是一个观察者