当前位置: 首页 > 知识库问答 >
问题:

使Dijkstra的算法考虑回程旅行时间

施俊哲
2023-03-14

所以问题如下:向我提供了一个未加权的树,并允许我从任何节点开始,我预计只访问数组中提供的某些节点。我的目标是找到前往每个所需节点所需的时间量。每个边缘都需要一分钟的时间。

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

共有1个答案

蒙峰
2023-03-14

我来详细说明一下我的评论:首先,我们会在树中固定一个任意的根,这样树就是有根的(可能你已经有一个有根的树了)。然后,第一步是找到一个最小长度的循环,它从根开始,到根结束,经过所有需要的节点。

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

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

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

//the tree from your example
var tree = { value: 90, children: [{ value: 50, children: [{ value: 20, children: [{ value: 5 }, { value: 25 }] }, { value: 75, children: [{ value: 66 }, { value: 80 }] }] }, { value: 150, children: [{ value: 95, children: [{ value: 92 }, { value: 111 }] }, { value: 175, children: [{ value: 166 }, { value: 200 }] }] }] };

var nodesToVisit = [90, 50, 20, 75];
//var nodesToVisit = [92, 111, 166];

function findCycle(treeNode, nodesToVisit) {
	var subPath = [];
	var currentNodeIncluded = false;
	if(nodesToVisit.indexOf(treeNode.value) != -1) {
		//this node should be visited
		subPath.push({node: treeNode, passThrough: false});
		currentNodeIncluded = true;
	}
	
	//find the subpath for all subtrees
	if(treeNode.children) {
		for(var i = 0; i < treeNode.children.length; ++i) {
			var subTreePath = findCycle(treeNode.children[i], nodesToVisit);
			if(subTreePath.length > 0) {
				if(!currentNodeIncluded) {
					subPath.push({node: treeNode, passThrough: true});
					currentNodeIncluded = true;
				}			
				//if we need to visit this subtree, merge it to the current path
				subPath = subPath.concat(subTreePath);
				subPath.push({node: treeNode, passThrough: true}); //go back to the current node
			}
		}
	}
	
	return subPath;
}

function removeLongestPassThroughSegment(cycle) {
	var longestSegmentStart = -1;
	var longestSegmentEnd = -1;
	
	//the start of the current pass-through segment between non-pass-through nodes
	var currentStart = -1;
	var segmentLengthAtStart = -1;
	for(var i = 0; i < cycle.length; ++i) {
		if(!cycle[i].passThrough) {
			//we have found a node that we need to visit
			if(currentStart != -1) {
				var length = i - currentStart;
				if(length > longestSegmentEnd - longestSegmentStart) {
					longestSegmentStart = currentStart;
					longestSegmentEnd = i;
				}
			} else
				segmentLengthAtStart = i;
			currentStart = i;
		}
	}
	
	//check the path segment that wraps around
	if(cycle.length - currentStart + segmentLengthAtStart > longestSegmentEnd - longestSegmentStart) {
		longestSegmentStart = currentStart;
		longestSegmentEnd = segmentLengthAtStart;
	}
	
	//build the final path by cutting the longest segment
	var path = [];
	var i = longestSegmentEnd;
	do {
		path.push(cycle[i]);
		i++;
		if(i >= cycle.length)
			i = 0;
	} while(i != longestSegmentStart);
	path.push(cycle[longestSegmentStart]);
	return path;
}

function printPath(path) {	
	for(var i = 0; i < path.length; ++i)
		if(path[i].passThrough)
			console.log("Pass through " + path[i].node.value);
		else
			console.log("Visit " + path[i].node.value);
}

var cycle = findCycle(tree, nodesToVisit);
console.log("Cycle:");
printPath(cycle);

var path = removeLongestPassThroughSegment(cycle);
console.log("Final Path:");
printPath(path);
 类似资料:
  • 本文向大家介绍Dijkstra的Java算法,包括了Dijkstra的Java算法的使用技巧和注意事项,需要的朋友参考一下 Dijkstra的算法是一种用于在加权图中的节点之间找到最短路径的算法。创建图形时,我们将使用新的addEdge和addDirectedEdge方法向边缘添加权重。让我们看看这个算法是如何工作的- 创建一个距离集合,并将除源节点以外的所有顶点距离设置为无穷大。 当距离为0时,

  • 同程offer到手了,补一下同程旅行的面经 岗位:算法工程师 base 北京 一面 技术面 主要问实习项目,然后结合项目问了一些八股 如果模型不收敛如何解决 如何判断训练过程中出现了梯度消失还是梯度爆炸 如何解决梯度消失和梯度爆炸 平常用哪些激活函数 介绍一下selu和swich激活函数,有什么优点 你在模型训练的过程当中用到了哪些小tricks 二面 技术面 为什么不继续做cv投搜推算法 实习项

  • 我们将用于确定最短路径的算法称为“Dijkstra算法”。Dijkstra算法是一种迭代算法,它为我们提供从一个特定起始节点到图中所有其他节点的最短路径。这也类似于广度优先搜索的结果。 为了跟踪从开始节点到每个目的地的总成本,我们将使用顶点类中的 dist 实例变量。 dist实例变量将包含从开始到所讨论的顶点的最小权重路径的当前总权重。该算法对图中的每个顶点重复一次;然而,我们在顶点上迭代的顺序

  • 一、迪杰斯特拉算法介绍 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径。 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。 基本思想 ​ 通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算)。 ​ 此外,引进两个集合S和U。S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是

  • 问题内容: 我正在尝试编写Dijkstra的算法,但是我在努力如何在代码中“说”某些事情而苦苦挣扎。为了可视化,这是我要使用数组表示的列: 因此,将有几个数组,如下面的代码所示: 粗体部分是我要坚持的地方-我正在尝试实现算法的这一部分: 3.对于当前节点,请考虑其所有未访问的邻居并计算其暂定距离。 例如,如果当前节点(A)的距离为6,并且将其与另一个节点(B)相连的边为2,则通过A到B的距离将为6

  • 我试图使用邻接列表和PQ作为最小堆来实现单目标最短路径的Dijkstra算法。输出必须显示所有顶点到目标顶点的路径,如果路径存在,如果是,它的总和(最短),如果否,否路径。链接到整个代码 输入格式: 第一行是顶点数,n 第二行开始:(从1到n的顶点) 第一列是顶点 之后,多对, 根据GDB,它显示了在提取最小函数时发现的分段故障。 客户. c 从文本中提取输入。txt文件并创建一个有向图 服务器.