【问题标题】:Traverse a graph from a starting point and ending at the starting point C++从起点遍历图形并在起点 C++ 结束
【发布时间】:2012-12-05 08:16:28
【问题描述】:

我正在开发一个 C++ 程序,在该程序中,我们必须以一种从用户指定的顶点开始,然后在经过一定的所需距离后在同一个顶点结束的方式遍历顶点和加权边图。 我不知道如何用代码实现它,但到目前为止我有这个:

void DijkstrasShortestPath()
{
    while (vertices.size() != 0)
    {
        Vertex* u = extract_min(vertices);
        vector<Vertex*>* adjVertex = AdjVertices(u);

        const int size = adjVertex->size();
        for (int i=0; i<size; ++i)
        {
            Vertex* v = adjVertex->at(i);
            int distance = travel_dist(u, v) +
                u->distFromStart;

            if (distance < v->distFromStart)
            {
                v->distFromStart = distance;
                v->previous = u;
            }
        }
        delete adjVertex;
    }
}

Vertex* extract_min(vector<Vertex*>& vertices)
{
    int size = vertices.size();
    if (size == 0) {
        return NULL;
    }
    int minimum = 0;
    Vertex* min = vertices.at(0);
    int i = 0;
    for( i=1; i<size; ++i)
    {
        Vertex* temp = vertices.at(i);
        if( temp->distFromStart < min->distFromStart) {
            min = temp;
            minimum = i;
        }
    }
    vertices.erase(vertices.begin() + minimum);
    return min;
}

vector <Vertex*>* AdjVertices(Vertex* vert)
{
    vector<Vertex*>* adjVertex = new vector <Vertex*> ();
    const int size = edges.size();
    for(int i=0; i<size; ++i)
    {
        Edge* edge = edges.at(i);
        Vertex* adjacent = NULL;
        if (edge->intersection1 == vert)
        {
            adjacent = edge->intersection2;
        }
        else if (edge->intersection2 == vert)
        {
            adjacent = edge->intersection1;
        }
        if (adjacent && vertices_check(vertices, adjacent))
        {
            adjVertex->push_back(adjacent);
        }
    }
    return adjVertex;
}

int travel_dist(Vertex* u, Vertex* v)
{
    const int size = edges.size();
    for(int i=0; i<size; ++i)
    {
        Edge* edge = edges.at(i);
        if (edge->street_connection(u, v))
        {
            return edge->distance;
        }
    }
    return -1;
}

bool vertices_check(vector<Vertex*>& vertices, Vertex* vert)
{
    const int size = vertices.size();
    for(int i=0; i<size; ++i)
    {
        if (vert == vertices.at(i))
        {
            return true;
        }
    }
    return false;
}

这本质上是 Dijkstra 的最短路径算法,这并不是我想要的。我想要做的是让程序计算距离在用户指定距离的 1 个单位内并且在同一个顶点开始和结束的路线。 有什么办法可以通过改变我所拥有的来做到这一点?

这是否需要广度优先搜索或深度优先搜索而不是 Dijkstra 算法?

【问题讨论】:

  • 如果您正在使用 C++ 中的图形,您应该查看Boost Graph Library。即使现成的算法(包括 Dijkstra 的最短路径)不能满足您的需求,您也可以得到一些很好的框架来以通用方式处理图形。
  • 你可以多次遍历一条边吗?您可以多次通过给定顶点吗?
  • 这个任务和在有向图中找某个循环是一样的吗?如果是这样,Google 有很多样本可供参考。
  • @Richard 只有起始顶点可以多次通过(因为我们需要从那里开始和结束),其他的只能通过一次。
  • @SChepurin 我们不需要找到一个特定的循环,我们只需要找到在同一顶点开始和结束并且总距离在用户指定距离的 1 个单位以内的任何路径.如果用户距离是不可能的,程序应该这样说。

标签: c++ graph path dijkstra


【解决方案1】:

Dijkstra 算法只会存储从起始节点到任何其他节点的最短路径。相反,您想要的是跟踪通向节点的所有路径。如果你有这些,你可以在每次找到到节点的新路径时检查是否有一条在之前找到的路径,其长度加上新路径的长度在用户指定距离的一个单位内。如果你然后走一条路向前走另一条路,你就有了循环。

【讨论】:

  • 哦,好吧,这是有道理的。那么,我将如何改变我所拥有的呢?显然我会删除 extract_min 函数,只通过每个相邻节点而不用担心最短路径,但是我应该做些什么来使这成为可能?
【解决方案2】:

一种可能的方法。

您可以使用有界的best-first search

创建一个结构P,它存储形成潜在循环的节点列表,以及到目前为止创建的循环的长度。

通过为S 链接到的每个节点创建一个单独的 P 结构,在指定的顶点 S 处播种搜索。将这些 P 结构添加到优先队列中,该队列按 P 结构描述的路径长度排序。

考虑这些节点中的每一个依次从优先级队列中删除它们的 P 结构,复制它们的 P 结构,并附加它们链接到的节点。如果要添加的节点已经存在于 P 结构中并且不是S,则丢弃该结构并且不再考虑该路由。同样,如果任何路径超过指定的成本C,则丢弃该路径并且不再考虑它。如果路径没有被丢弃,则将其关联的 P 结构添加到优先级队列中。

如果S确实出现在P结构中两次,并且P结构描述的路径长度在允许的范围内,则成功退出。如果没有,继续搜索,直到priortiy-queue为空。

您可以通过使用admissible heuristic 来猜测从给定节点到S 的距离,将其添加到进行中路径的既定成本,并使用总和作为优先级队列的排序键。这种启发式是A* algorithm 的核心,您可能会感兴趣。

这清楚吗?如果没有,我可以写一个简短的示例代码。

【讨论】:

    猜你喜欢
    • 2016-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-16
    • 1970-01-01
    相关资源
    最近更新 更多