0

I have a Directed Cyclic Graph and need to find longest path from point A to point B. The graph is a 2D array. I already wrote code that can find longest path in Acyclic Graph, but when I change the graph to the Cyclic one it doesn't work. Here's the code:

#include <iostream>
#include <queue>
#include <list>
#include <stack>
#include <limits.h>

#define NINF INT_MIN
//#define NINF -1 

struct vec2 {
    int x, y;
};

class AdjListNode {
    vec2 v;
    int weight;

public:
    AdjListNode(vec2 _v, int _w)
    {
        v.x = _v.x;
        v.y = _v.y;

        weight = _w;
    }
    vec2 getV() { return {v.x, v.y}; }
    int getWeight() { return weight; }
};

class Graph {
    vec2 V;

    std::list<AdjListNode> adj[8][8];

    void topologicalSortUtil(vec2 v, bool visited[8][8], std::stack<vec2>& Stack);

public:
    Graph(int V_x, int V_y);
    ~Graph();

    void addEdge(vec2 u, vec2 v, int weight);

    void longestPath(vec2 s);
};

Graph::Graph(int V_x, int V_y)
{
    V.x = V_x;
    V.y = V_y;
}

Graph::~Graph()
{
}

void Graph::addEdge(vec2 u, vec2 v, int weight)
{
    if (v.x == 0 && v.y == 0) //So we have no edge back to the root node
        return;

    AdjListNode node(v, weight);
    adj[u.x][u.y].push_back(node);
}

void Graph::topologicalSortUtil(vec2 v, bool visited[8][8], std::stack<vec2>& Stack)
{
    visited[v.x][v.y] = true;

    std::list<AdjListNode>::iterator i;
    for (i = adj[v.x][v.y].begin(); i != adj[v.x][v.y].end(); i++) {
        AdjListNode node = *i;
        if (!visited[node.getV().x][node.getV().y])
        {
            topologicalSortUtil({ node.getV().x, node.getV().y }, visited, Stack);
        }
    }

    Stack.push(v);
}

void Graph::longestPath(vec2 s)
{
    std::stack<vec2> Stack;
    int dist[8][8];

    std::vector<vec2> path;
    vec2 pred[8][8];

    bool visited[8][8];
    for (int i = 0; i < V.x; i++)
        for (int j = 0; j < V.y; j++)
            visited[i][j] = false;

    for (int i = 0; i < V.x; i++)
        for (int j = 0; j < V.y; j++)
            if (visited[i][j] == false)
                topologicalSortUtil({ i, j }, visited, Stack);

    for (int i = 0; i < V.x; i++)
        for (int j = 0; j < V.y; j++)
            dist[i][j] = NINF;
    dist[s.x][s.y] = 0;

    for (int i = 0; i < V.x; i++)
        for (int j = 0; j < V.y; j++)
            pred[i][j] = {NINF, NINF};

    while (Stack.empty() == false) {
        vec2 u = Stack.top();
        Stack.pop();

        std::list<AdjListNode>::iterator i;
        if (dist[u.x][u.y] != NINF) {
            for (i = adj[u.x][u.y].begin(); i != adj[u.x][u.y].end(); i++) {
                if (dist[i->getV().x][i->getV().y] < dist[u.x][u.y] + i->getWeight())
                {
                    dist[i->getV().x][i->getV().y] = dist[u.x][u.y] + i->getWeight();

                    pred[i->getV().x][i->getV().y].x = u.x;
                    pred[i->getV().x][i->getV().y].y = u.y;
                }
            }
        }
    }

    for (int i = 0; i < V.x; i++)
        for (int j = 0; j < V.y; j++)
            (dist[i][j] == NINF) ? std::wcout << "INF " : std::wcout << "dist[" << i << "][" << j << "] :" << dist[i][j] << " ";

    int maxDist = 0;
    vec2 nodeIdx;

    for (int i = 0; i < V.x; i++)
        for (int j = 0; j < V.y; j++)
        {
            if (dist[i][j] > maxDist)
            {
                maxDist = dist[i][j];
                nodeIdx.x = i;
                nodeIdx.y = j;
            }
        }

    std::wcout << "\nmaxDist: " << maxDist << "\n";
    std::wcout << "nodeIdx: {" << nodeIdx.x << "," << nodeIdx.y << "} \n";

    for (int i = 0; i < V.x; i++)
        for (int j = 0; j < V.y; j++)
            std::wcout << "pred[" << i << "][" << j <<"] :" << "{" << pred[i][j].x << "," << pred[i][j].y << "}\n";

    vec2 crawl = {nodeIdx.x, nodeIdx.y};
    path.push_back(crawl);
    while ((pred[crawl.x][crawl.y].x != NINF) &&
        (pred[crawl.x][crawl.y].y != NINF))
    {
        path.push_back(pred[crawl.x][crawl.y]);
        crawl = pred[crawl.x][crawl.y];
    }

    std::wcout << "\nPath is::\n";
    for (int i = path.size() - 1; i >= 0; i--)
        std::wcout << "{" << path[i].x << "," << path[i].y << "} ";
}

int main()
{
    Graph g(8, 8);

    //This is a test graph
    //This acyclic graph works just fine and returns the longest path
    g.addEdge({ 0, 0 }, { 1, 1 }, 1);
    g.addEdge({ 0, 0 }, { 3, 3 }, 1);
    g.addEdge({ 0, 0 }, { 7, 7 }, 1);
    g.addEdge({ 1, 1 }, { 2, 2 }, 1);
    g.addEdge({ 3, 3 }, { 4, 4 }, 1);
    g.addEdge({ 3, 3 }, { 7, 7 }, 1);
    g.addEdge({ 4, 4 }, { 5, 5 }, 1);
    g.addEdge({ 4, 4 }, { 6, 6 }, 1);
    g.addEdge({ 4, 4 }, { 7, 7 }, 1);
    g.addEdge({ 5, 5 }, { 6, 6 }, 1);
    g.addEdge({ 6, 6 }, { 7, 7 }, 1);

    //But when I add this and make the graph cyclic it doesn't work as intended
    //g.addEdge({ 2, 2 }, { 0, 0 }, 1);
    //g.addEdge({ 2, 2 }, { 3, 3 }, 1);
    //g.addEdge({ 3, 3 }, { 2, 2 }, 1);

    vec2 s = {0, 0};
    std::wcout << "Following are longest distances from source vertex {"
        << s.x << "," << s.y << "}\n";
    g.longestPath(s);

    return 0;
}

The code was taken from: https://www.geeksforgeeks.org/find-longest-path-directed-acyclic-graph/ and modified to take 2D points as input instead of 1D points. The code was also modified based on: https://www.geeksforgeeks.org/shortest-path-unweighted-graph/ and https://www.geeksforgeeks.org/longest-path-undirected-tree/ to show the actual path instead of distance

That is my final graph/2D array that I need to get the longest path from

g.addEdge({0,0}, {1,1},1);
g.addEdge({0,0}, {2,2},1);
g.addEdge({0,0}, {3,3},1);
g.addEdge({0,0}, {4,4},1);
g.addEdge({0,0}, {5,5},1);
g.addEdge({0,0}, {6,6},1);
g.addEdge({0,0}, {7,7},1);
g.addEdge({0,1}, {1,0},1);
g.addEdge({0,2}, {1,2},1);
g.addEdge({0,2}, {2,2},1);
g.addEdge({0,2}, {3,2},1);
g.addEdge({0,2}, {4,2},1);
g.addEdge({0,2}, {5,2},1);
g.addEdge({0,2}, {6,2},1);
g.addEdge({0,2}, {7,2},1);
g.addEdge({0,3}, {0,4},1);
g.addEdge({0,3}, {0,5},1);
g.addEdge({0,3}, {0,6},1);
g.addEdge({0,3}, {0,7},1);
g.addEdge({0,4}, {1,4},1);
g.addEdge({0,4}, {2,4},1);
g.addEdge({0,4}, {3,4},1);
g.addEdge({0,4}, {4,4},1);
g.addEdge({0,4}, {5,4},1);
g.addEdge({0,4}, {6,4},1);
g.addEdge({0,4}, {7,4},1);
g.addEdge({0,5}, {0,6},1);
g.addEdge({0,5}, {0,7},1);
g.addEdge({0,6}, {1,5},1);
g.addEdge({0,6}, {2,4},1);
g.addEdge({0,6}, {3,3},1);
g.addEdge({0,6}, {4,2},1);
g.addEdge({0,6}, {5,1},1);
g.addEdge({0,6}, {6,0},1);
g.addEdge({0,7}, {1,7},1);
g.addEdge({0,7}, {2,7},1);
g.addEdge({0,7}, {3,7},1);
g.addEdge({0,7}, {4,7},1);
g.addEdge({0,7}, {5,7},1);
g.addEdge({0,7}, {6,7},1);
g.addEdge({0,7}, {7,7},1);
g.addEdge({1,0}, {1,1},1);
g.addEdge({1,0}, {1,2},1);
g.addEdge({1,0}, {1,3},1);
g.addEdge({1,0}, {1,4},1);
g.addEdge({1,0}, {1,5},1);
g.addEdge({1,0}, {1,6},1);
g.addEdge({1,0}, {1,7},1);
g.addEdge({1,1}, {1,2},1);
g.addEdge({1,1}, {1,3},1);
g.addEdge({1,1}, {1,4},1);
g.addEdge({1,1}, {1,5},1);
g.addEdge({1,1}, {1,6},1);
g.addEdge({1,1}, {1,7},1);
g.addEdge({1,2}, {0,2},1);
g.addEdge({1,3}, {2,3},1);
g.addEdge({1,3}, {3,3},1);
g.addEdge({1,3}, {4,3},1);
g.addEdge({1,3}, {5,3},1);
g.addEdge({1,3}, {6,3},1);
g.addEdge({1,3}, {7,3},1);
g.addEdge({1,4}, {0,4},1);
g.addEdge({1,5}, {2,5},1);
g.addEdge({1,5}, {3,5},1);
g.addEdge({1,5}, {4,5},1);
g.addEdge({1,5}, {5,5},1);
g.addEdge({1,5}, {6,5},1);
g.addEdge({1,5}, {7,5},1);
g.addEdge({1,6}, {2,7},1);
g.addEdge({1,7}, {0,6},1);
g.addEdge({2,0}, {2,1},1);
g.addEdge({2,0}, {2,2},1);
g.addEdge({2,0}, {2,3},1);
g.addEdge({2,0}, {2,4},1);
g.addEdge({2,0}, {2,5},1);
g.addEdge({2,0}, {2,6},1);
g.addEdge({2,0}, {2,7},1);
g.addEdge({2,1}, {3,1},1);
g.addEdge({2,1}, {4,1},1);
g.addEdge({2,1}, {5,1},1);
g.addEdge({2,1}, {6,1},1);
g.addEdge({2,1}, {7,1},1);
g.addEdge({2,2}, {2,1},1);
g.addEdge({2,2}, {2,0},1);
g.addEdge({2,3}, {3,2},1);
g.addEdge({2,3}, {4,1},1);
g.addEdge({2,3}, {5,0},1);
g.addEdge({2,4}, {1,3},1);
g.addEdge({2,4}, {0,2},1);
g.addEdge({2,5}, {2,6},1);
g.addEdge({2,5}, {2,7},1);
g.addEdge({2,6}, {3,6},1);
g.addEdge({2,6}, {4,6},1);
g.addEdge({2,6}, {5,6},1);
g.addEdge({2,6}, {6,6},1);
g.addEdge({2,6}, {7,6},1);
g.addEdge({2,7}, {2,6},1);
g.addEdge({2,7}, {2,5},1);
g.addEdge({2,7}, {2,4},1);
g.addEdge({2,7}, {2,3},1);
g.addEdge({2,7}, {2,2},1);
g.addEdge({2,7}, {2,1},1);
g.addEdge({2,7}, {2,0},1);
g.addEdge({3,0}, {4,1},1);
g.addEdge({3,0}, {5,2},1);
g.addEdge({3,0}, {6,3},1);
g.addEdge({3,0}, {7,4},1);
g.addEdge({3,1}, {4,2},1);
g.addEdge({3,1}, {5,3},1);
g.addEdge({3,1}, {6,4},1);
g.addEdge({3,1}, {7,5},1);
g.addEdge({3,2}, {4,3},1);
g.addEdge({3,2}, {5,4},1);
g.addEdge({3,2}, {6,5},1);
g.addEdge({3,2}, {7,6},1);
g.addEdge({3,3}, {2,2},1);
g.addEdge({3,3}, {1,1},1);
g.addEdge({3,4}, {4,4},1);
g.addEdge({3,4}, {5,4},1);
g.addEdge({3,4}, {6,4},1);
g.addEdge({3,4}, {7,4},1);
g.addEdge({3,5}, {2,5},1);
g.addEdge({3,5}, {1,5},1);
g.addEdge({3,5}, {0,5},1);
g.addEdge({3,6}, {4,5},1);
g.addEdge({3,6}, {5,4},1);
g.addEdge({3,6}, {6,3},1);
g.addEdge({3,6}, {7,2},1);
g.addEdge({3,7}, {2,7},1);
g.addEdge({3,7}, {1,7},1);
g.addEdge({3,7}, {0,7},1);
g.addEdge({4,0}, {3,0},1);
g.addEdge({4,0}, {2,0},1);
g.addEdge({4,0}, {1,0},1);
g.addEdge({4,1}, {4,2},1);
g.addEdge({4,1}, {4,3},1);
g.addEdge({4,1}, {4,4},1);
g.addEdge({4,1}, {4,5},1);
g.addEdge({4,1}, {4,6},1);
g.addEdge({4,1}, {4,7},1);
g.addEdge({4,2}, {3,3},1);
g.addEdge({4,2}, {2,4},1);
g.addEdge({4,2}, {1,5},1);
g.addEdge({4,2}, {0,6},1);
g.addEdge({4,3}, {3,2},1);
g.addEdge({4,3}, {2,1},1);
g.addEdge({4,3}, {1,0},1);
g.addEdge({4,4}, {5,5},1);
g.addEdge({4,4}, {6,6},1);
g.addEdge({4,4}, {7,7},1);
g.addEdge({4,5}, {5,6},1);
g.addEdge({4,5}, {6,7},1);
g.addEdge({4,6}, {3,5},1);
g.addEdge({4,6}, {2,4},1);
g.addEdge({4,6}, {1,3},1);
g.addEdge({4,6}, {0,2},1);
g.addEdge({4,7}, {5,7},1);
g.addEdge({4,7}, {6,7},1);
g.addEdge({4,7}, {7,7},1);
g.addEdge({5,0}, {4,0},1);
g.addEdge({5,0}, {3,0},1);
g.addEdge({5,0}, {2,0},1);
g.addEdge({5,0}, {1,0},1);
g.addEdge({5,1}, {5,2},1);
g.addEdge({5,1}, {5,3},1);
g.addEdge({5,1}, {5,4},1);
g.addEdge({5,1}, {5,5},1);
g.addEdge({5,1}, {5,6},1);
g.addEdge({5,1}, {5,7},1);
g.addEdge({5,2}, {6,1},1);
g.addEdge({5,2}, {7,0},1);
g.addEdge({5,3}, {6,3},1);
g.addEdge({5,3}, {7,3},1);
g.addEdge({5,4}, {4,4},1);
g.addEdge({5,4}, {3,4},1);
g.addEdge({5,4}, {2,4},1);
g.addEdge({5,4}, {1,4},1);
g.addEdge({5,4}, {0,4},1);
g.addEdge({5,5}, {6,5},1);
g.addEdge({5,5}, {7,5},1);
g.addEdge({5,6}, {4,6},1);
g.addEdge({5,6}, {3,6},1);
g.addEdge({5,6}, {2,6},1);
g.addEdge({5,6}, {1,6},1);
g.addEdge({5,6}, {0,6},1);
g.addEdge({5,7}, {5,6},1);
g.addEdge({5,7}, {5,5},1);
g.addEdge({5,7}, {5,4},1);
g.addEdge({5,7}, {5,3},1);
g.addEdge({5,7}, {5,2},1);
g.addEdge({5,7}, {5,1},1);
g.addEdge({5,7}, {5,0},1);
g.addEdge({6,0}, {6,1},1);
g.addEdge({6,0}, {6,2},1);
g.addEdge({6,0}, {6,3},1);
g.addEdge({6,0}, {6,4},1);
g.addEdge({6,0}, {6,5},1);
g.addEdge({6,0}, {6,6},1);
g.addEdge({6,0}, {6,7},1);
g.addEdge({6,1}, {6,2},1);
g.addEdge({6,1}, {6,3},1);
g.addEdge({6,1}, {6,4},1);
g.addEdge({6,1}, {6,5},1);
g.addEdge({6,1}, {6,6},1);
g.addEdge({6,1}, {6,7},1);
g.addEdge({6,2}, {6,3},1);
g.addEdge({6,2}, {6,4},1);
g.addEdge({6,2}, {6,5},1);
g.addEdge({6,2}, {6,6},1);
g.addEdge({6,2}, {6,7},1);
g.addEdge({6,3}, {6,4},1);
g.addEdge({6,3}, {6,5},1);
g.addEdge({6,3}, {6,6},1);
g.addEdge({6,3}, {6,7},1);
g.addEdge({6,4}, {6,5},1);
g.addEdge({6,4}, {6,6},1);
g.addEdge({6,4}, {6,7},1);
g.addEdge({6,5}, {5,4},1);
g.addEdge({6,5}, {4,3},1);
g.addEdge({6,5}, {3,2},1);
g.addEdge({6,5}, {2,1},1);
g.addEdge({6,5}, {1,0},1);
g.addEdge({6,6}, {6,5},1);
g.addEdge({6,6}, {6,4},1);
g.addEdge({6,6}, {6,3},1);
g.addEdge({6,6}, {6,2},1);
g.addEdge({6,6}, {6,1},1);
g.addEdge({6,6}, {6,0},1);
g.addEdge({6,7}, {5,7},1);
g.addEdge({6,7}, {4,7},1);
g.addEdge({6,7}, {3,7},1);
g.addEdge({6,7}, {2,7},1);
g.addEdge({6,7}, {1,7},1);
g.addEdge({6,7}, {0,7},1);
g.addEdge({7,0}, {6,1},1);
g.addEdge({7,0}, {5,2},1);
g.addEdge({7,0}, {4,3},1);
g.addEdge({7,0}, {3,4},1);
g.addEdge({7,0}, {2,5},1);
g.addEdge({7,0}, {1,6},1);
g.addEdge({7,0}, {0,7},1);
g.addEdge({7,1}, {6,1},1);
g.addEdge({7,1}, {5,1},1);
g.addEdge({7,1}, {4,1},1);
g.addEdge({7,1}, {3,1},1);
g.addEdge({7,1}, {2,1},1);
g.addEdge({7,1}, {1,1},1);
g.addEdge({7,1}, {0,1},1);
g.addEdge({7,2}, {6,2},1);
g.addEdge({7,2}, {5,2},1);
g.addEdge({7,2}, {4,2},1);
g.addEdge({7,2}, {3,2},1);
g.addEdge({7,2}, {2,2},1);
g.addEdge({7,2}, {1,2},1);
g.addEdge({7,2}, {0,2},1);
g.addEdge({7,3}, {6,3},1);
g.addEdge({7,3}, {5,3},1);
g.addEdge({7,3}, {4,3},1);
g.addEdge({7,3}, {3,3},1);
g.addEdge({7,3}, {2,3},1);
g.addEdge({7,3}, {1,3},1);
g.addEdge({7,3}, {0,3},1);
g.addEdge({7,4}, {6,4},1);
g.addEdge({7,4}, {5,4},1);
g.addEdge({7,4}, {4,4},1);
g.addEdge({7,4}, {3,4},1);
g.addEdge({7,4}, {2,4},1);
g.addEdge({7,4}, {1,4},1);
g.addEdge({7,4}, {0,4},1);
g.addEdge({7,5}, {7,6},1);
g.addEdge({7,5}, {7,7},1);
g.addEdge({7,6}, {7,5},1);
g.addEdge({7,6}, {7,4},1);
g.addEdge({7,6}, {7,3},1);
g.addEdge({7,6}, {7,2},1);
g.addEdge({7,6}, {7,1},1);
g.addEdge({7,6}, {7,0},1);

The graph has 64 points each having from 1 to 7 edges (connections). Last point {7, 7} has no connections going out and only connections going to that point. Some points have connections to each other, for example point {5, 2} connects to point {7, 0} and point {7, 0} connects to point {5, 2}. Also the path needs to go from Point {0, 0} to Point {7, 7} and ideally reach every point.

The fact that the longest path is from point {0, 0} to point {7, 7} and that the path goes through every point is sure. But I need to get the exact path

Now the program show that the longest path from point {0, 0} is to point {0, 4} which isn't true.

Already tried to find solution online, found some Stack Overflow questions, but the answers didn't satisfy my because most of them were very general and explaining only concepts which I couldn't in 100% understand and thus implement.

halfer
  • 19,824
  • 17
  • 99
  • 186
dawidsk12345
  • 67
  • 1
  • 8
  • There is no term ՛Directed Cyclic Graph՛․ There is a term Directed Acyclic Graph which means a directed graph that does not contain cycles. There is a term Directed Graph which means a directed graph, which may or may not contain cycles. – ArthurBesse Jul 10 '22 at 17:55
  • 1
    Finding longest path in directed acyclic graph is a well known problem and there is a well known algorithm to solve this problem. However, finding the longest path in a directed graph is an NP complete problem. This means that at the moment there is no polynomial time algorithm to solve this problem. The one who finds such an algorithm is waiting for a big prize. So, do not expect a longest path algorithm in a directed acyclic graph to find a longest path in a directed graph. – ArthurBesse Jul 10 '22 at 18:06
  • @ArthurBesse Ok, I didn't know that, thanks for letting me know. So, is there any other way to find a path from point {0, 0} to {7, 7} that will go through every point on the way? So, to add some context it's a "Arrow Maze" puzzle like this one http://www.cross-plus-a.com/html/cros7armz.htm, and I need to find solution for this and I know that some people already wrote their programs for that. Do you know any other algorighm that will find a solution for this? – dawidsk12345 Jul 10 '22 at 18:30
  • `g.addEdge({7,1}, {1,1},1); g.addEdge({7,1}, {0,1},1); g.addEdge({7,2}, {6,2},1); g.addEdge({7,2}, {5,2},1); g.addEdge({7,2}, {4,2},1); g.addEdge({7,2}, {3,2},1); g.addEdge({7,2}, {2,2},1); g.addEdge({7,2}, {1,2},1); g.addEdge({7,2}, {0,2},1); g.addEdge({7,3}, {6,3},1); g.addEdge({7,3}, {5,3},1); g.addEdge({7,3}, {4,3},1);` - wow, you actually wrote that? No thought of using loops or a data file or anything? – Jesper Juhl Jul 10 '22 at 18:30
  • @JesperJuhl No, I didn't write it. There's a separate class and array of data for that, but didn't want to copy everything here, because that's too much code, so I added a cout to the addEdge function and then just copied here the console output – dawidsk12345 Jul 10 '22 at 18:36
  • 1
    @dawidsk12345 If problem is NP-complete it just means that no polynomial algorithm is known for that problem. So, you can use a non-polynomial algorithm. For example, brute-force all possible paths starting in {0, 0}, choose those that end in {7, 7}, and choose the longest of them. – ArthurBesse Jul 10 '22 at 18:47

0 Answers0