I'm looking if there is a known solution for the task I have in mind
Given: Undirected graph with V > 100k nodes. Most of the vertices have a degree of 1-2, but some of them might have up to 10-20k edges.
I'm interested in all simple paths between two vertices or all paths ending on the start verticle limited by maxLength. Path can't contain the visited nodes but might end on the start node.
Goal: Occasionally some graph's edges are updated in batch. I'd like to find out what routes between vertices of interest were updated. Ideally in the form of Iterator but List is fine too.
Effectively I'm looking for a reactive way to find out about the affected routes.
The implementation could be in any language but Java/Kotlin specific is more preferred :)
Any references/relevant information would be very appreciated.
I wasn't sure if it's a question for CS StackExchange but it looks more relevant to SO.
To find paths between two nodes that do not share any nodes except the start and end.
Run Dijskta to find shortest simple path between start, end
Add large cost ( = largest integer for example ) to the in-edges of all nodes on shortest path, except start,end
Repeat until no new path found with cost less than largest integer
To find out what routes between vertices of interest were updated. This is trivial
- Multimap of edges, keyed by route index
- Vector of updated edges
- Loop over updated edges
- IF edge in multimap
- print index of affected route
Related
Here is graph searching problem In Facebook Hacker Cup. Problem Link
Problem Description:
MXN Matrix we have to find the minimum distance from source to target. There are lasers which changes direction and Also Fires laser in every step we take.
Problem:
I have used the same approach is described in the Editorial But i have used DFS instead of BFS and i am getting wrong answer to some of the case.How the DFS is making a Difference Why DFS is not working on this while BFS work.
Code LINK
tHanks
Editorial
It is pretty simple. If you need to find the shortest path in an unweighted graph, you should use BFS. If you need a specific traversal order(like in topological sort), you should use DFS. If the order and the lenght of the path doesn't matter, you can use any of them. In this problem the shortest path is required, so BFS is an obvious choice(DFS doesn't work because it finds some path, not necessarily the shortest one).
The particular reason why BFS is good for finding the shortest path is that BFS traverses nodes in such an order, that all the nodes that have the distance X to the source node are processed before all the nodes that have the distance X+1. This allows for a very simple and efficient way of finding the shortest path in the graph between two nodes: as you add a node to the queue, you know its distance to the source is 1 more that the node you are processing at the moment (it can't be smaller, otherwise it already would have been in the queue). If with the distance for each node you also remember which node you came to it from, you can easily restore the shortest path itself.
DFS traverses nodes in a different order, and hence can't be easily adjusted to find the shortest path.
BFS -
Cases where you can use BFS-
1: To find minimum length path in an unweighted graph.
2: Level order traversal of a tree.
DFS:
Cases where you can use DFS-
1: To find any valid solution to a problem.
2: To check for existence of any path in a graph.
NOTE - Though they can be used in many other places.
I have a directed graph with a special root node from which all other nodes are reachable.
It is quite easy to find an arbitrary algorithm to find all pathes from a giving node to the root, for example this solution (DFS) using LinkedHashSets.
Well, this algorithm works well for small graphs but with larger graphs it doesn't come to an end in a reasonable amount of time.
My example graph has 129 nodes and 200 edges. In my eyes not an extremly HUGE graph...
Can somebody give me a hint how to solve this problem efficiently?
Maybe we can make use of other properties of my graphs. They all are:
connected
directed with loops
have a designated starting node
have a designated end node
Well, not really - you cannot make it significantly more efficient, because the output size itself is huge. The number of paths is exponential in the number of nodes, have a look at this simple example:
V = {a, b, c}, E = {(a,b), (a,c), (b,c)}
This looks pretty simple, there are "only" 2 none trivial paths in the graph leading to c. a->c, a->b->c.
Now, consider adding a node d with edges (d,a), (d,b) - you will have 3 paths leading to c from the new root, d->a->b->c, d->a->c, d->b->c, still not too bad, but notice what happens when adding e with (e,d),(e,a), you will get one "family" of paths starting with e->d (3 above paths), and in addition, "family" of paths starting with "e->a" (2 paths). totaling in 5 paths. By repeating the process, you will get another two families, one with 5 paths, and the other with 3 paths. You probably start to understand that if you repeat the process k times, you will get #fibo(k) different paths, but the fibonacci number is very, very big for inputs such as 100 (~354*10^20, and keeps growing fast).
Thus, whatever you do - finding all paths in a graph is going to be inefficient, except for some "easy" graphs, such as trees.
tl;dr:
There are exponential number of paths leading to your target node, and finding all of them takes exponential time. DFS is a solid solution for this problem.
I was wondering if this problem is known in graph theory:
I have an undirected graph with no weights G=(V,A) and I want to place the nodes of this graph in a string so that directed nodes are placed as much close as possible. So for example:
Given this graph:
a,b;a,d;b,e;c,f;c,h;f,h;e,g;e,h.
where arcs are separated by ';'
I need to get to this solution:
a,b,d,e,g,h,c,f=2
where 2 is the maximum distance in the string a,b,d,e,g,h,c,f between two directed nodes.
Formally:
let d(v,u) be the distance between two nodes according to the graph.
Find an order v1,,v2,,vn,, such that max{d(vi,,vi+1,) } is minimal
Well, it seems you are facing a variation of the Hamiltonian Path Problem.
In this problem, given a graph - you are looking for a path that go through all vertices without repeating any node twice.
Note that a hamiltonian path is a perfect solution to your problem, and thus if your problem can be solved efficiently - so does the hamiltonoan path problem.
Unfortunately, there is no known polynomial solution for the hamiltonian path problem, and the problem is NP-Complete (so the general belief is such a (efficient) solution does not exist).
A brute force solution will be O(n!) - check all possible permutations, and choose the optimal one. This can be optimized using branch and bound techniques.
I am developing a simple program to calculate the shortest path from one city to other, using directed weighted nodes of a graph to represent a train trail map.
So far I tried Bellman-Ford, Dijkstra, Floyd-Warshall and Johnson algorithms and all of them are good to find the shortest path to a different destination which is not the same as the start.
But when I need to calculate the path between city A and back to city A through other cities, I always get 0 value because those methods ignore the path from a city to itself in order to don't get caught in an infinity loop.
I know that it might be simple to resolve that loop problem by creating another parameter which is target to aim the algorithm to stop when it catches this target node, but I don't have the skill to modify one of those libraries.
Can anyone show me the way?
My graph is AB5 - BC4 - CD8 - DC8 - DE6 - AD5 - CE2 - EB3 - AE7 and the distance from B to B should be 9, but in all those algorithms it's returning 0.
Note: it's not a duplicate, since nobody bothered so far on finding routes at ends at the beginning, as I searched on StackOverflow and Google, at least in Java.
A simple approach would be to use the shortest path algorithms/libraries that you already have with a modified graph. You could duplicate each node and the corresponding adjacent outgoing edges, and then find the shortest path from the duplicated node to the original one.
Here is how the transformation would look like for A-A path (without weight for simplicity):
I have a graph in which i have two nodes (0 and 6) and i have to cut the least edges possible so that they aren´t connected. For example in this graph
Being the nodes 0 and 6 the least edges that i have to cut are 2-7 and 3-7.
My idea was finding the shortest path between the both using bfs, i find one (0-2-7-6) but then i don´t know how to find the other (0-3-7-6). Even then i have no idea how choose the edges to cut.
It would be nice if someone could give me some pointers on this matter.
This problem seems very similar to that of finding articulation nodes within a graph. The technical definition of an articulation point, or a biconnected component is a node whose removal would cause a graph to be split in two.
The discovery of articulated nodes from a graph is a largely solved problem and you can find more details about it here: http://en.wikipedia.org/wiki/Biconnected_component
It seems to me that the way you would like to approach a problem like this in general would something along these lines:
1. Find all articulation points
2. Do a bfs from each node and determine articulation points along the path
3. Split graph at the articulation point, choosing the side with minimal edges
4. Continue until the two nodes are not connected
In the above example, 7 is the only articulation point and so you would snip the edges between 7, 2 and 3 since there are only two edges between 7 and the 0-4 graph and 3 edges between 7 and the 5,6,8 graph.
There is a more established algorithm for doing this (read: one that I didn't come up with) called Karger's algorithm that can solve your problem, albeit in n^2 time.
That algorithm works by effectively joining adjacent nodes to each other until there are only two nodes and then by counting the number of edges left between the two nodes. The number of edges is then the minimum number of cuts required to split the graph.
The way you would implement Karger's algorithm in your problem would just need the caveat that you should always be joining nodes to the two nodes you want to split. Additionally, in order to be able to go backward to the original edges you need to cut you should keep a reference to which nodes the edges originally belonged to.
There's a great visualization of Karger's algorithm here: http://en.wikipedia.org/wiki/Karger%27s_algorithm
What you want is a min s-t cut. The usual way to find one in a general graph is to run an algorithm like push relabel with source 0 and sink 6, which computes a min s-t cut as a byproduct of computing a maximum flow.
Karger's algorithm finds a min cut, i.e., it minimizes over s and t as well as cuts. Since s and t are fixed for you, Karger's is not appropriate. An articulation vertex is a vertex whose removal disconnects the graph. You are interested in removing edges, not vertices.