loveMeansNothing
loveMeansNothing

Reputation: 361

Longest path in unweighted undirected graph

Undirected Unweighted graph

Having this graph as reference let's say i want the longest path between 0 and 5.

That would be: 0->1->3->2->4->6->5

Is there any good algorithm for this? I've searched and haven't found anything that i was able to understand. I've found plenty algorithms for the shortest path (0->1->2->4->6->5) and i've implemented them successfully. Maybe i'm the problem, but i would like to think otherwise :)

Any help would be welcome

Upvotes: 4

Views: 4683

Answers (1)

kraskevich
kraskevich

Reputation: 18546

This problem is NP-Hard (there is a simple reduction from a Hamiltonian path to your problem, and a Hamiltonian path search is known to be NP-hard). It means that there is no polynomial solution for this problem (unless P = NP).

If you need an exact solution, you can use dynamic programming (with exponential number of states): the state is (mask of visited vertices, last_vertex), the value is true or false. A transition is adding a new vertex which is not in the mask if there an edge between the last_vertex and the new vertex. It has O(2^n * n^2) time complexity, which is still better than O(n!) backtracking.

Here is pseudo code of a dynamic programming solution:

f = array of (2 ^ n) * n size filled with false values
f(1 << start, start) = true
for mask = 0 ... (1 << n) - 1:
    for last = 0 ... n - 1:
        for new = 0 ... n - 1:
            if there is an edge between last and new and mask & (1 << new) == 0:
                f(mask | (1 << new), new) |= f(mask, last)
res = 0
for mask = 0 ... (1 << n) - 1:
    if f(mask, end):
        res = max(res, countBits(mask))
return res

And a little bit more about reduction from Hamiltonian path to this problem:

def hamiltonianPathExists():
    found = false
    for i = 0 ... n - 1:
        for j = 0 ... n - 1:
            if i != j:
                path = getLongestPath(i, j) // calls a function that solves this problem
                if length(path) == n:
                    found = true
    return found

Here is a Java implementation (I did not test properly, so it can contain bugs):

/**
 * Finds the longest path between two specified vertices in a specified graph.
 * @param from The start vertex.
 * @param to The end vertex.
 * @param graph The graph represented as an adjacency matrix.
 * @return The length of the longest path between from and to.
 */
public int getLongestPath(int from, int to, boolean[][] graph) {
    int n = graph.length;
    boolean[][] hasPath = new boolean[1 << n][n];
    hasPath[1 << from][from] = true;
    for (int mask = 0; mask < (1 << n); mask++)
        for (int last = 0; last < n; last++)
            for (int curr = 0; curr < n; curr++)
                if (graph[last][curr] && (mask & (1 << curr)) == 0)
                    hasPath[mask | (1 << curr)][curr] |= hasPath[mask][last];
    int result = 0;
    for (int mask = 0; mask < (1 << n); mask++)
        if (hasPath[mask][to])
            result = Math.max(result, Integer.bitCount(mask));
    return result;
}

Upvotes: 3

Related Questions