【问题标题】:Finding the shortest paths of a directed graph C++找到有向图 C++ 的最短路径
【发布时间】:2015-05-07 14:29:29
【问题描述】:

上周,我通过解析输入文件实现了有向图。该图保证没有循环。我已经成功地创建了图,使用方法返回了顶点和边的数量,并对图进行了拓扑排序。该图由不同的主要课程及其先决条件组成。这是我的图表设置:

class vertex{
public:
    typedef std::pair<int, vertex*> ve;     
    std::vector<ve> adjacency;              
    std::string course;                     
    vertex(std::string c){
        course = c;
    }
};

class Digraph{
public:
    typedef std::map<std::string, vertex *> vmap;           
    vmap work;
    typedef std::unordered_set<vertex*> marksSet;           
    marksSet marks;
    typedef std::deque<vertex*> stack;                      
    stack topo;
    void dfs(vertex* vcur);                                 
    void addVertex(std::string&);                           
    void addEdge(std::string& from, std::string& to, int cost);     
    int getNumVertices();                                   
    int getNumEdges();                                      
    void getTopoSort();                                     

};

实现

//function to add vertex's to the graph
void Digraph::addVertex(std::string& course){
    vmap::iterator iter = work.begin();
    iter = work.find(course);
    if(iter == work.end()){
        vertex *v;
        v = new vertex(course);
        work[course] = v;
        return;
    }
}

//method to add edges to the graph
void Digraph::addEdge(std::string& from, std::string& to, int cost){
    vertex *f = (work.find(from)->second);
    vertex *t = (work.find(to)->second);
    std::pair<int, vertex *> edge = std::make_pair(cost, t);
    f->adjacency.push_back(edge);
}

//method to return the number of vertices in the graph
int Digraph::getNumVertices(){
    return work.size();
}

//method to return the number of edges in the graph
int Digraph::getNumEdges(){
    int count = 0;
    for (const auto & v : work) {
         count += v.second->adjacency.size();
     }
     return count;
}

//recursive function used by the topological sort method
void Digraph::dfs(vertex* vcur) {
  marks.insert(vcur);
  for (const auto & adj : vcur->adjacency) {
    vertex* suc = adj.second;
    if (marks.find(suc) == marks.end()) {
      this->dfs(suc);
    } 
  }
  topo.push_front(vcur);
}

//method to calculate and print out a topological sort of the graph
void Digraph::getTopoSort(){
    marks.clear();
    topo.clear();
    for (const auto & v : work) {
        if (marks.find(v.second) == marks.end()) {
            this->dfs(v.second);
        }
    }
    // Display it
   for (const auto v : topo) {
    std::cout << v->course << "\n";
  }
}

在我实施的最后一部分,我一直在尝试做两件事。找到从第一个顶点到每个其他顶点的最短路径,并找到访问每个顶点并返回第一个顶点的最短路径。我完全迷失了这个实现。我从阅读中假设我需要使用 Dijkstra 的算法来实现这一点。最近3天我一直在尝试,但无济于事。我是否以错误的方式设置了我的有向图来实施这些步骤?任何指导表示赞赏。

【问题讨论】:

  • 听起来有点像traveling salesman problems
  • 如果没有循环,你将如何回到原来的顶点?回溯?
  • @SeanKuhlman 我不得不回溯。
  • 你的意思是有向图——有向图是完全不同的东西。
  • @dwcanillas 这是为大学设置的课程地图。权重是注册课程所需的分数。

标签: c++ graph graph-algorithm dijkstra shortest-path


【解决方案1】:

没有循环的事实使问题变得更加简单。找到最短路径和最小的“环游”是 O(n)。

实现 Dijkstra 并运行它,没有“目标”节点;继续下去,直到所有节点都被访问过。一旦每个节点都被标记(以及它到根的距离),您可以从任何节点开始,并通过始终步入距离小于该距离的唯一邻居,沿着最短(也是唯一)的路径返回根。如果你愿意,你可以很容易地构建这些路径,并用返回根的完整路径标记每个节点,但是如果复制这些路径可以将成本推高到 O(n2)你不小心。

一旦标记了所有节点,您就可以构建一个最小的大游览。从根开始;当您访问一个节点时,遍历其未访问的邻居(即除了您刚刚来自的那个之外的所有邻居),访问每个节点,然后返回您来自的那个。 (如果你愿意,我可以用更严谨的数学来说明这个问题,或者举个例子。)

【讨论】:

  • 举个例子就好了。我已尝试实施您的建议,但无济于事。
猜你喜欢
  • 2018-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-25
相关资源
最近更新 更多