Weighted Graph Algorithm - algorithm

I have a weighted, directed graph with multiples edges starting from the ending at the same nodes.
Ex.
Multiple edges going from node A to node B.
What would be the best search algorithm to get all of the paths to a certain node and the associated costs of these paths?

Since you want all the paths, I'd use a simple breadth-first search. However, I also suggest that you collapse all the parallel edges into a single edge that has a list of weights.
Once you get all the different paths (that is, all the paths in which the nodes visited are different), for each path you can calculate all the possible alternative parallel routes.
So if you've got the following edges:
A -> C (5)
A -> C (3)
A -> B (7)
B -> C (1)
B -> C (4)
The first step transforms it into:
A -> C (5,3)
A -> B (7)
B -> C (1,4)
The breadth-first search on this graph will yield the following paths between A and B:
A -> B (7)
A -> C -> B (5,3) + (1,4)
So for the second path, you'll get the following costs:
5 + 1
5 + 4
3 + 1
3 + 4
This isn't going to be any faster in itself than just doing a BFS on the original graph, but a simpler graph is easier to handle.

If you have to output the cost of each path, there is nothing better than a plain DFS (or BFS). Since the problem is output sensitive and you might just have O(E + V) paths, you cannot accomplish anything better in terms of big-O notation.

As already stated, you can do bruteforce/backtracking using Depth First Search, etc.
Don't expect to find any shortcuts for this - if your graph is dense enough there can be lots of paths and even just finding how many of them there are is #P-complete (ie.: untractable).
(If your problem is different - maybe repeated nodes are allowed or you only want to find the shortest path or something like that then there could be tractable solution)

do you allow the cycling, that is you have directed link/path from a->b b-x-x-->a? for which case you will end up with unlimited paths.

Related

Shortest path with another constraint

Given a weighted undirected graph, I need to find the shortest path between two nodes, a classical shortest path problem actually. But there is one more constraint : Each node contains a "reduction" value that can be used to reduce the cost of the following edges for one traversal(not only adjacent, and reduction are not cumulative). So you can reduce the cost of an edge using the "Reduction" that was in one of the node you went throught before (the final cost for each edge can't be less than 0).
Note that once we went throught a node with a reduction, we can use it again for all the following edges (not just adjacent, and it is available an unlimited amount of time). Reduction doesn't accumulate.
Let's consider this graph :
in this graph the shortest path from node 1 to 5 is :
1 -> 4 for a cost of 13 (15-2)
4 -> 3 for a cost of 0 (12-12)
3 -> 5 for a cost of 0 (10-12) In this case, we reuse the reduction of node 4 because it is bigger than the reduction of node 3 (We went throught the node n°4 then we have an unlimited amount of reduction of cost 12). It is 0 and not -2 because the weight of an edge can't be negative.
Then the total cost from node 1 to node 5 is 13 + 0 + 0 = 13
To solve this problem, I've tried to use the classical Dijkstra/Bellman-Ford but it didn't work, can you help me with this ?
It seems to be this can be solved with a variation of Bellman-Ford.
Every path up to a given node can be summarised as a pair (C, D) where C is the cost of that path (after discounts) and D is the best discount factor available on that path. Since a discount can be reused an unlimited number of times once that node has been visited, it makes sense to always use the biggest discount seen so far on that path. For example, the path (1 -> 4 -> 3) has cost C = 13 and discount D = 12.
The complication over the undiscounted problem is that we cannot tell from the cost what the "best" path is to nodes in between the source and destination. In your example the path (1 -> 2 -> 3) has lower cost than (1 -> 4 -> 3), but the latter has a better discount which is why the best path from 1 to 5 is (1 -> 4 -> 3 -> 5).
Rather than recording the lowest cost path to each node (in Bellman-Ford algorithm), we need to record all "feasible" paths from the source to that node found so far. A path can be said to be feasible if there is no other known path that has both a lower cost and a better discount. After the algorithm terminates we can take from all feasible paths from source to destination the one with the smallest cost, ignoring the discount.
(Edit: I originally suggested Djikstra could be used but I think that not be so straightforward. I'm not sure we can choose "the closest" unvisited node in any meaningful way such that we are guaranteed to find the minimal path. Someone else might see how to make it work though...)
I think you can use a Dijkstra-type algorithm. Dijkstra's algorithm can be thought of computing the minimum spanning tree that contains the shortest paths from a source vertex to all other vertices. Let's call this the "Dijkstra tree" that contains all the shortest paths from a given source vertex.
Dijkstra keeps adding new vertices to the current tree. For the next vertex he chooses the one that is closest to the current tree. See this animation from wikipedia:
So when Dijkstra adds a new vertex v to an already inserted vertex u (of the current tree), the edge weight of {u, v} has to be considered. In your case, the costs are not just the edge weight of {u, v}, but the weight reduced by the sum of vertex-reductions along the shortest path to u in the current tree. So you have to remember the sum of the vertex reductions along the paths of this "Dijkstra" tree in the vertices.

Dijkstra with parallel edges between two Vertices

I've got a routing problem where I need to retrieve the best n solutions between two points. I am using Dijkstra for the optimal solution and Yen Top K algorithm on top of that to get the n best solutions.
However there is a twist to it, you can have multiple parallel edges between to vertices. Lets imagine a bus network:
Line A: a -> b -> c -> d -> e
Line B: b -> c -> d -> e -> f
Line C: a -> b -> c -> g -> h
When you build your graph, how do you handle these parallel connections?
I am thinking of building the graph like:
Line A: a->b,a->c,a->d a->e,b->c,b->d,b->d,b->e,c->d,c->e,d->e
Line B: b->c,b->d,b->e,e->f,c->d,c->e,c->f,d->e,d->f,e->f
Line C: a->b,a->c,a->g,a->h,b->c,b->g,b->h,c->g,c->h,g->h
With that I have direct edges for when I don't have to change bus.
For each Vertex I go through I add a connection penalty weight.
So if I want to go from a->e I would probably get Line A as using Line C a->b, Line B b->e might be longer because of the connection time even if the time Line C a->b and Line B b->e might be faster than the route on Line A.
However I still need to handle parallel connections. So I guess I need to sort the parallel edges by weight.
Currently this is based on static timing information but at some point it should take actual schedule information into account. And depending on that your weights between two vertices could change. E.g. by the time you would get to point b the fastest connection via Line C wouldn't be the fastest anymore as you would have just missed Line C etc.
Are there any resources anywhere that explain how you would handle these more complex situations?
One approach could be to reduce the problem back to a simple graph (no parallel edges), by "splitting nodes"
That means, if you have a node u, with edges (v,u)_1, (v,u)_2, ..., (v,u)_k, you can split u to: u, u_1, u_2,...,u_k, with edges: (u_1,u), (u_2,u), ..., (u_k,u), (v,u_1), (v,u_2), ...., (v,u_k), and weights:
w(u_i,u) = 0 for all i and w(v,u_i) = w((v,u)_i) for all i
Now you can run any algorithm designed for simple graph with ease, where the number of vertices is increased in a linear factor of the number of parallel edges.

Find the all chain of one to one node in graph

I go the un-directed graph G an my goal is to find all the possible chains longest than N of nodes in a one to one relation.
For example:
In the the next Graph the "chains" of length more than 2 of nodes in one to one relation are:
- d -> e -> f -> g
- c -> k -> l -> m
So what is the best approach or algorithm to solve this problem ?
If you want to find all paths so that each vertex in it has a degree <=2, then the simple approach may be as follows.
Remove all vertices with degree >2 from your graph. You are left with a graph with each vertex having a degree <=2. It is easy to prove that every connected component of such a graph is either a simple way, either a simple loop, and it is easy to distinguish them (for example, running a DFS from one node and seeing whether you ever return to it).
So, every component that is a path is a path you look for. Every component that is a loop is also a path you look for, or can be easily converted to such a path by removing an edge or a vertex, depending on whether you allow a loop as the needed path.

Is this a proper algorithm that would accept graph G if it's connected?

I wanted to ask and see if this suffices in creating a polynomial time algorithm given a Graph P? Just want to double check.
On input (P,u,v) where P is an undirected graph with nodes u and v:
Create a list D of every edge in graph P with numbers from x_0 to x_k.
Select node u as the starting node. Utilizing BFS, traverse through the graph until the current node is the initial u value.
Repeat with using x_0 onwards through the list until x_k is used.
If BFS completes, accept. Otherwise, reject.
I believe my problem lets with the accept/rejection condition but what would it be in this case?
Your question doesn't make sense in a lot of ways, but from what I can tell, no.
Your step 2 will (slowly) find a cycle, which is not useful.
I have no clue what step 3 is supposed to be and your variable v is unused (and having u as as parameter doesn't make sense).
For an directed graph, you need to specify whether you want to check for weak connectivity (like a undirected graph) or strong connectivity.
For weak connectivity, you need to:
Take as input a graph G
Create a local, empty, set S for seen nodes.
Do a depth first search (including backwards links - watch your algorithmic complexity with how you look them up!) from some node, adding each node to S as you visit it, and skipping edges that lead from the current node to a node in S during iteration. (You can use a breadth-first search if you allocate an additional data set for the frontier)
Check whether S has the same number of nodes as G.
For strong connectivity, you need to check that the graph is connected regardless of which node you set at. There's probably a way to do this more efficiently than repeating the above for every node.
An example graph (consider this from any starting node):
1 -> 2
2 -> 3
3 -> 1
3 -> 4
4 -> 5
5 -> 6
6 -> 4

Dijkstra's Algorithm Does not generate Shortest Path?

I am working through a shortest path problem using Dijkstra's Algorithm. I am having trouble because the algorithm is supposed to provide the shortest path, but after running the algorithm I get a shorted path by hand. Is this just a by-product of this algorithm?
The path I am trying to generate is from a -> z
Here is the path that I get from applying the algorithm, taking the shortest distance jump at each vertex I visit:
2 4 2 2 1 2 1 1 8 = 23
a -> d -> g -> k -> r -> n -> q -> p -> t -> z
This is confusing to me because if I take this path:
4 2 2 2 2 2 2 = 16
a -> c -> f -> i -> m -> p -> s -> z
I get a distance that is 5 less than the distance generated from the algorithm.
Did I misstep somewhere?
Looks like you misunderstand how Dijkstra's algorithm works. Instead of taking the edge with the smallest weight at each node, you always need to consider the total distance from the beginning (node $a$). You maintain a heap of all possible paths under consideration, which starts off as just the starting node with no edges and expands by adding all the paths with each outgoing edge of a node added to the path you're currently considering at each step.
That's a jumble of words trying to summarise where you went wrong. I suggest re-reading how Dijkstra's algorithm works: http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm

Resources