Search code examples
c++graph-theorybreadth-first-searchshortest-pathlemon-graph-library

Lemon graph how to find all paths between two nodes


I'm using the Lemon C++ library for graphs, and what I need to do is to find all the paths between two nodes. I'm able to find a single path (the shortest), but I need all of them.

Is there a way to achieve this with Lemon?

// Create the graph
ListDigraph g;

ListDigraph::Node a = g.addNode();
ListDigraph::Node b = g.addNode();
ListDigraph::Node c = g.addNode();
ListDigraph::Node d = g.addNode();
ListDigraph::Node e = g.addNode();

ListDigraph::Arc a_b = g.addArc(a, b);
ListDigraph::Arc b_c = g.addArc(b, c);
ListDigraph::Arc c_d = g.addArc(c, d);
ListDigraph::Arc a_e = g.addArc(a, e);
ListDigraph::Arc e_d = g.addArc(e, d);

// Assign labels to edges and arcs
ListDigraph::NodeMap<std::string> nodeValues(g);
nodeValues[a] = "a";
nodeValues[b] = "b";
nodeValues[c] = "c";
nodeValues[d] = "d";
nodeValues[e] = "e";

ListDigraph::ArcMap<std::string> arcValues(g);
arcValues[a_b] = "a->b";
arcValues[b_c] = "b->c";
arcValues[c_d] = "c->d";
arcValues[a_e] = "a->e";
arcValues[e_d] = "e->d";

// Find the shortest path
Bfs<ListDigraph> bfs(g);
bfs.init();
bfs.addSource(a);
bfs.start();

if (bfs.reached(c))
{
    std::cout << nodeValues[c];
    ListDigraph::Node prev = bfs.predNode(c);
    while (prev != INVALID)
    {
        std::cout << "<-" << nodeValues[prev];
        prev = bfs.predNode(prev);
    }
    std::cout << std::endl;
}

=> c<-b<-a

Solution

  • Thanks to srt1104 comment this is how I "solved" the problem, assuming I'm looking for all the paths between a and d.

    Dfs<ListDigraph> dfs(g);
    dfs.init();
    dfs.addSource(a);
    
    std::vector<ListPath<ListDigraph>> paths;
    ListPath<ListDigraph> currPath;
    ListDigraph::Node prevNode = a;
    
    while (!dfs.emptyQueue())
    {
        ListDigraph::Arc arc = dfs.processNextArc();
    
        if (g.source(arc) == prevNode)
        {
            currPath.addBack(arc);
            prevNode = g.target(arc);
        }
        else
        {
            prevNode = g.target(arc);
            currPath = {};
            currPath.addBack(arc);
        }
    
        if (g.target(arc) == d)
        {
            paths.push_back(currPath);
        }
    }
    
    cout << "Paths.." << endl;
    
    for (auto path : paths)
    {
        for (int i = 0; i < path.length(); i++)
        {
            cout << arcValues[path.nth(i)] << " ";
        }
    
        cout << endl;
    }
    
    ---------
    Paths..
    a->e e->d 
    a->b b->c c->d