Search code examples
algorithmgraphdynamic-programmingcycle

Given a directed weighted graph with self loops ,find the list of nodes that are exactly k dist from a given node x?


Each edge in the graph has weight of 1,The graph may have cycles ,if a node has self loop it can be any distance from itself from 0 to infinity , depending on the no. of time we take the self loop.

I have solved the problem using bfs, but the constraint on distance is in order of 10^9 ,hence bfs is slow.

We ll be asked multiple queries on a given graph of the form (distance , source) and the o/p is the list of nodes that are exactly at the given distance starting from the source vertex.

Constraints

1<=Nodes<=500
1<queries<=500
1<=distance<=10^9

I have a feeling ,there would be many repeated computations as the no. of nodes are small,but i am not able to figure out how do i reduce the problem in smaller problems.

What is the efficient way to do this?

Edit : I have tried using matrix exponentiation but its too slow ,for the given constraints. The problem has a time limit of 1 sec.


Solution

  • Let G = (V,E) be your graph, and define the adjacency matrix A as follows:

    A[i][j] = 1       (V[i],V[j]) is in E
              0       otherwise
    

    In this matrix, for each k:

    (A^k)[i][j] > 0 if and only if there is a path from v[i] to v[j] of length exactly k.
    

    This means by creating this matrix and then calculating the exponent, you can easily get your answer.

    For fast exponent calculation you can use exponent by squaring, which will yield O(M(n)^log(k)) where M(n) is the cost for matrix multiplication for nXn matrix.

    This will also save you some calculation when looking for different queries on the same graph.

    Appendix - claim proof:

    Base: A^1 = A, and indeed in A by definition, A[i][j]=1 if and only if (V[i],V[j]) is in E

    Hypothesis: assume the claim is correct for all l<k

    A^k = A^(k-1)*A. From induction hypothesis, A^(k-1)[i][j] > 0 iff there is a path of length k-1 from V[i] to V[j].

    Let's examine two vertices v1,v2 with indices i and j.
    If there is a path of length k between them, let it be v1->...->u->v2. Let the index of u be m.
    From i.h. A^(k-1)[i][m] > 0 because there is a path. In addition A[m][j] = 1, because (u,v2) = (V[m],V[j]) is an edge.

    A^k[i][j] = A^(k-1)*A[i][j] = A^(k-1)[i][1]A[1][j] + ... + A^(k-1)[i][m]A[m][j] + ... + A^(k-1)[i][n]A[n][j] 
    

    And since A[m][j] > 0 and A^(k-1)[i][m] > 0, then A^(k-1)*A[i][j] > 0

    If there is no such path, then for each vertex u such that (u,v2) is an edge, there is no path of length k-1 from v to u (otherweise v1->..->u->v2 is a path of length k).

    Then, using induction hypothesis we know that if A^(k-1)[i][m] > 0 then A[m][j] = 0, for all m.
    If we assign that in the sum defining A^k[i][j], we get that A^k[i][j] = 0

    QED

    Small note: Technically, A^k[i][j] is the number of paths between i and j of length exactly k. This can be proven similar to above but with a bit more attention to details.
    To avoid the numbers growing too fast (which will increase M(n) because you might need big integers to store that value), and since you don't care for the value other than 0/1 - you can treat the matrix as booleans - using only 0/1 values and trimming anything else.