6

This is the question: Given a directed graph G=(V,E), a source vertex s $epsilon V, we know that all cycles in G are of positive weight ( > 0). Also we are given the graph after Bellman-Ford was run on it, meaning that for each v in V we know both d[v] (shortest path from s to v) and pi[v] (v's predecessor)

Describe an algorithm to find the number of shortest path from s to v for all v in V. The algorithm must run in O(V+E)

*We cannot edit the Bellman-Ford run on the algorithm

This is what i thought of: We run a modified DFS,

Algorithm(G,s):

1.DFS-Visit(G,s)
2. return count[v] foreach v in V

DFS-Visit(G,u):

1.foreach v in Adj[u]
   2.if d[v] == d[u] + w(u,v) && (u,v) is not a backedge
      3.count[v] = count[v] + 1
      4.DFS-visit(G,v)

*It seems like the algorithm can get stuck in an infinite loop, maybe i can ignore back-edges? (since a shortest path will always be simple)

*This is not a duplicate of How to find the number of different shortest paths between two vertices, in directed graph and with linear-time?

in that question the graph is unweighted here it is weighted ( edges) Do you think this is correct? Thanks

Community
  • 1
  • 1
Bilal27
  • 75
  • 1
  • 5

2 Answers2

3

if d[v] == d[u] + w(u,v) && (u,v) is not a backedge

The condition d[v]==d[u]+w(u,v) is the most important here. If guarantees that this is never a backedge and, moreover, it guarantees that you will never return to the vertex where you have been.

Indeed, assume you returned to a vertex where you have been. Then you have

d[v1]==d[v0]+w(v0,v1)
d[v2]==d[v1]+w(v1,v2)
...
d[v0]==d[vn]+w(vn,v0)

summing it all, we find that

w(v0,v1)+w(v1,v2)+...+w(vn,v0)==0

that is a zero-weight loop, but we are told there is no such loops.

So this algorithm will never stuck into a infinite loop; moreover, if you leave only the edges satisfying d[v]==d[u]+w(u,v) (making graph directed even if it has not been), the resulting graph will be acyclic.

Therefore you can run the standard algorithm of finding a number of ways in an acyclic graph. In fact this is what you have already written (your DFS), just note that

count[v] = count[v] + 1

should be

count[v] = count[v] + count[u]
Petr
  • 9,812
  • 1
  • 28
  • 52
  • How can i be sure that keeping the edges satisfying the condition will give me an acyclic graph? Thanks for the answer – Bilal27 May 24 '15 at 14:36
  • @Bilal27 (I'm spitballing since I only skimmed this) The answer is probably that if there were cycles in it, we could remove them to get shorter paths since you said only positive-weight cycles exist. – G. Bach May 24 '15 at 14:44
  • @Bilal27, the proof is absolutely similar to the proof in the beginning of my post. – Petr May 24 '15 at 14:47
0

The DFS modified in the way described in the question (with the corrections from the accepted answer) allows visiting a node multiple times and can lead to an exponential time algorithm (see counterexample below for the general structure of a graph where this happens).

If we visit every node once like in classical DFS, the algorithm doesn't always count correctly the number of shortest paths.

Counterexample

7 nodes, 8 edges, all weights are 1

1 -> 2
1 -> 5
2 -> 3
5 -> 3
3 -> 4
3 -> 6
4 -> 7
6 -> 7

General structure looks something like this

  2   4
 / \ / \
1   3   7
 \ / \ /
  5   6

After running Bellman-Ford starting from node 1:

d[1] = 0
d[2] = d[5] = 1
d[3] = 2
d[4] = d[6] = 3
d[7] = 4

There are 4 different shortest paths from node 1 to node 7:

1 2 3 4 7
1 2 3 6 7
1 5 3 4 7
1 5 3 6 7

But applying DFS we get:

count[1] = 1
Visiting node 1: count[2] = 1
Visiting node 2: count[3] = 1
Visiting node 3: count[4] = 1
Visiting node 4: count[7] = 1
Visiting node 7: no outgoing arcs
Returning to node 4: no more neighbors
Returning to node 3: count[6] = 1
Visiting node 6: count[7] = 2
Node 7 already visited, so we skip it
Returning to node 6: no more neighbors
Returning to node 3: no more neighbors
Returning to node 2: no more neighbors
Returning to node 1: count[5] = 1
Visiting node 5: count[3] = 2

And this is where the algorithm ends if don't allow visiting nodes multiple times, so count[7] will remain 2, which is incorrect (correct would have been 4). If we allow visiting a node multiple times, the running time will be of the magnitude of 2^n.

Correct algorithm

As demonstrated in Petr's answer, the edges along shortest paths form a directed acyclic graph (DAG). We need to sort the nodes of this DAG topologically and apply the counting algorithm on the nodes in the topological order. Running time is O(n + m): one complete traversal of the graph for the topological sorting and one complete traversal of the graph for the counting algorithm.

Correct algorithm demonstrated on counterexample

One possible topological order: 1 2 5 3 4 6 7
Visiting nodes in this order:
count[1] = 1
Visiting 1: count[2] = 1, count[5] = 1
Visiting 2: count[3] = 1
Visiting 5: count[3] = 2
Visiting 3: count[4] = 2, count[6] = 2
Visiting 4: count[7] = 2
Visiting 6: count[7] = 4