Работает ли эта реализация алгоритма Дейкстры для мультиграфов? - PullRequest
0 голосов
/ 15 апреля 2019

Я бы хотел использовать алгоритм Дейкстры для мультиграфов. Мой алгоритм выглядит следующим образом:

#include <queue>
#include <vector>
#include <cstddef>

using namespace std;

class Edge;
class Node;

//
// Class "Node"
//
class Node
{
public:
   Node();
   vector<Edge*> my_edges; //edges incident to this node
   Node* ancestor; //ancestor of this node in the spanning tree
   Edge* bond; //spanning-tree edge linking this node to its ancestor
   double distance; //distance of this node from a source (briefly: "node distance")
   int co_id; //serial number of the graph component including this node
};

//
// Class "Edge"
//
class Edge
{
public:
   Edge();
   Node *start, *end; //starting and ending nodes of this edge
   double weight; //weight of this edge
   Node* get_neig_node(Node* node) //method returning the neighbor of "node"
   {
      if (start == node)
      {
         return end;
      }
      else
      {
         return start;
      }
   }
};

//
// Function "Dijkstra"
//
void dijkstra(vector<Node*> nodes)
{
   struct dijkstra_aux
   {
      //
      // Internal struct performing a "Dijkstra run" from a source
      //
      static void dijkstra_map(Node* source, int co_id)
      {
         //
         // Declare the local variables
         //
         Node *node, *neig_node; //a node and its neighbor
         Edge* edge; //an edge
         priority_queue<pair<double, Node*>, vector<pair<double, Node*>>,
            greater<pair<double, Node*>>> prior_queue; 
               //priority queue storing the (distance,node) pairs
         double sum; //auxiliary variable

         //
         // Initialize the members of "source"
         //
         source->ancestor = NULL;
         source->bond = NULL;
         source->distance = 0.0;

         //
         // Minimize the node distances
         //
         prior_queue.push(make_pair(source->distance, source));
         while (prior_queue.size() != 0)
         {
            //
            // Take "node" out of the queue and save its parameters
            //
            node = prior_queue.top().second;
            node->co_id = co_id;
            prior_queue.pop();

            //
            // Go through the edges of this node
            //
            for (int j = 0; j < (int)node->my_edges.size(); j++)
            {
               edge = node->my_edges[j];
               neig_node = edge->get_neig_node(node);
               sum = node->distance + edge->weight;
               if (sum < neig_node->distance)
               {
                  neig_node->ancestor = node;
                  neig_node->bond = edge;
                  neig_node->distance = sum;
                  prior_queue.push(make_pair(neig_node->distance, neig_node));
               }
            }
         }
      }
   };

   //
   // Declare the local variables
   //
   Node* node; //a given node
   Edge* edge; //a given edge
   double max_dist; //maximum node distance
   int co_id; //iterator over the graph components

   //
   // Estimate the maximum node distances
   //
   max_dist = -1.0;
   for (int i = 0; i < (int)nodes.size(); i++)
   {
      node = nodes[i];
      node->co_id = -1;
      for (int j = 0; j < (int)node->my_edges.size(); j++)
      {
         edge = node->my_edges[j];
         if (edge->weight > max_dist) max_dist = edge->weight;
      }
   }
   max_dist *= (double)nodes.size();

   //
   // Declare all the node distances to "max_dist"
   //
   for (int i = 0; i < (int)nodes.size(); i++)
      nodes[i]->distance = max_dist;

   //
   // Run the "dijkstra_map" function by graph components
   //
   co_id = -1;
   for (int i = 0; i < (int)nodes.size(); i++)
   {
      node = nodes[i];
      if (node->co_id == -1)
      {
         co_id++;
         dijkstra_aux::dijkstra_map(node, co_id);
      }
   }
}

В функции dijkstra в переменной Node::bond.

сохраняются не только предки узлов, но и ребра дерева кратчайшего пути.

Как вы думаете, это работает для мультиграфов? Если нет, можете ли вы предложить модификацию, позволяющую использовать этот код для обработки нескольких ребер?

...