【问题标题】:Dijkstra's algorithm - comparisons in priority queueDijkstra 算法 - 优先级队列中的比较
【发布时间】:2014-06-04 22:14:21
【问题描述】:

我在 C++ from this page 中复制了 dijkstra 的算法,并对其进行了修改以适合我的图形表示类。基本上,我只用我自己的结构edge替换了std::pair作为std::set的模板参数:

struct edge
{
    int vertex;
    unsigned long weight;

    edge(int v = 0, unsigned long wt = 0) : vertex(v), weight(wt) { }

    bool operator<(const edge& e2) const
    {
        //return weight < e2.weight;
        return weight < e2.weight || ((e2.weight >= weight) && vertex < e2.vertex);
    }
};

但是,我必须实现 operatore2.weight >= weight(所以e2.weight实际上可能weight更大)只要vertex &lt; e2.vertex,更长的语句就会返回true。但是顶点数没有出现在 Dijkstra 算法的定义中。

那么为什么程序只使用第二个 return 语句就可以正常工作呢?

【问题讨论】:

  • int vertex 代表什么?
  • 链接页面中的secondstd::pair 相同。
  • 在您链接的页面中,第二个元素是vertex_t。它使用int,所以它有一个唯一标识符 - int 的大小没有意义(所以在比较中使用它没有意义)
  • 该页面中的 vertex_t 是在while 循环开始时从std::set 弹出的顶点的当前处理邻居。它的价值很重要,因为它只是表示weight_t 所指的顶点。但我同意比较没有意义 - 但是,就像我说的那样,我的operator&lt; 中的第一个 return 语句导致我的程序在某些在线法官的最大输入测试中失败(给出错误答案)。这个测试包含超过 5k 的顶点和超过 100k 的边,所以我很难检查它在运行时的行为。
  • 这可能与 set 是根据其元素上的某些 operator&lt;() 自动排序的事实有关,因此在这种情况下,在使用 set 的情况下,大小为vertex 可能包含有关其与其他元素相关的排序的有用信息?

标签: c++ algorithm set graph-algorithm dijkstra


【解决方案1】:

改写正确的返回语句:

return (this->weight < e2.weight) || ((this->weight <= e2.weight) && this->vertex < e2.vertex);

相当于:

return (this->weight < e2.weight) || ((this->weight == e2.weight) && this->vertex < e2.vertex);

所以我希望我的体重更轻....或者如果相等,顶点更小。

edit(误解了原文为什么会失败): 标准集需要严格的排序......

当您插入图形边时,这些边的权重可以相同 - 因此,权重本身并不是边的唯一标识符,因此它与 Djikstra 的逻辑排序机制无关 - 它是保持所有边缘而不在集合中相互覆盖的方式。

对于更明显的失败案例,请尝试使用 op 的两个定义来执行此操作<:>

//int verticeIdx[4] = {0, 1, 2, 3} 
int constWeight = 3;
edge myEdge(0, constWeight), myNewEdge(1, constWeight);
std::set<edge> edges;
edges.insert(myEdge);
edges.insert(myNewEdge);
std::cout << edges.size();

【讨论】:

  • 是的,我刚刚注意到我们可以将&lt;= 分解为==...感谢在operator&lt; 中考虑vertex,这些元素按权重和顶点排序数字(按顺序) - 就像你说的。但是 Dijkstra 算法的定义表明我们只需从容器中取出具有最低权重的元素 - 它没有说明在重复权重的情况下还要考虑顶点数。这就是为什么我不知道为什么我的第一个 return 语句使算法不正确。
  • @Quentin,如果 operatorEdgeSetLesser > myEdges; ............. 这使您可以根据 Djikstra 的权重使用单独的比较器,并根据不同的标准进行排列/组织。
  • Awww,我完全忘记了“仅权重并不是边缘的唯一标识符”这一事实。现在一切都清楚了,谢谢!
猜你喜欢
  • 2013-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多