Finding the closest marked node in a graph - algorithm

In a graph with a bunch of normal nodes and a few special marked nodes, is there a common algorithm to find the closest marked node from a given starting position in the graph?
Or is the best way to do a BFS search to find the marked nodes and then doing Dijkstra's on each of the discovered marked nodes to see which one is the closest?

This depends on the graph, and your definition of "closest".
If you compute "closest" ignoring edge weights, or your graph has no edge weights, a simple breadth-first search (BFS) will suffice. The first node reached vía BFS is, by definition of BFS, the closest (or, if there are several closest nodes, tied for closeness). If you keep track of the number of expanded BFS levels, you can locate all closest nodes by reaching the end of the level instead of stopping as soon as you find the first marked node.
If you have edge weights, and need to use them in your computation, use Dijkstra instead. If the edges can have negative weights, and there happen to be any negative cycles, then you will need to instead use Bellman-Ford.
As mentioned by SaiBot, if the start node is always the same, and you will perform several queries with changing "marked" nodes, there are faster ways to do things. In particular, you can store in each node the "parent" found in a first full traversal, and the node's distance to the start node. When adding a new batch of k marked nodes, you would immediately know the closest to the start by looking at this distance for each marked node.

The fastest way would be to perform Dijkstra right away from your starting position (starting node). When "closeness" is defined as the number of edges that have to be traversed, you can just assign a weight of 1 to each edge. In case precomputation is allowed there will be faster ways to do it.

Related

Algorithm to visit every node in a directed cyclic graph

As the title says, I have a graph that contains cycles and is directed. It's strongly connected so there's no danger of getting "stuck". Given a start node, I want to find the a path (ideally the shortest but that's not the thing I'm optimising for) that visits every node.
It's worth saying that many of the nodes in this graph are frequently connected both ways - i.e. it's almost undirected. I'm wondering if there's a modified DFS that might work well for this particular use case?
If not, should I be looking at the Held-Karp algortihm? The visit once and return to starting point restrictions don't apply for me.
The easiest approach would probably be to choose a root arbitrarily and compute a BFS tree on G (i.e., paths from the root to each other vertex) and a BFS tree on the transpose of G (i.e., paths from each other vertex to the root). Then for each other vertex you can navigate to and from the root by alternating tree paths. There are various quick optimizations to this method.
Another possibility would be to use A* on the search space consisting of states current node × set of visited nodes, with heuristic equal to the number of nodes not visited yet. The worst-case running time is comparable to Held–Karp (which you could also apply after running Floyd–Warshall to form a complete unsymmetric distance matrix).

Shortest path algorithms

I have questions about an optimal algorithm problem on a weighted graph. I am given an edgelist with weights, a list with savepoints, a starte- and end- node and the max distance for a step.
The output should be a list of savepoints, which are accessible in one step from starting- and end- node.
I thought of some kind of dijkstra's algorithm from each point of the list of savepoints.
I'm not sure if that's a good idea, since if I have many savepoints I calculate a lot of paths multiple times. Every idea/help is welcome!
Thank you very much in advance!
You have to have the condition that a weight cannot be negative, otherwise the problem becomes very intractable. Otherwise it's just a breadth first search, with marking the distance for every visited node. So you don't revisit a node is a previous move has visited it earlier at lower cost.
You keep a priority queue of all active nodes, so you are checking the lowest cost node each time. The priority queue is in fact the hardest part to get right. If you check the A* algorithm for my binary image library https://github.com/MalcolmMcLean/binaryimagelibrary you can take the priority queue for there. A* over a maze is very similar to shortest path over a graph, but you don't have a heuristic because you must have the exact shortest path, and instead of 4 / 8 edges per tile, you have nodes with arbitrary numbers of connections.

How to get path from one node to all other nodes in a weighted tree in minimum time?

I just want to get the distance of source node from every node. But it is different than graph problems since it is a tree and path between every node is unique so I expect answer to be in more efficient time.
Is it possible to get answer in efficient time?
You're absolutely right that in a tree, the difficulty of finding a path between two nodes is a lot lower than in a general graph because once you find any path (at least, one without cycles) you know it's the shortest. So all you have to do is just find all paths starting at the given node and going to each other node. You can do this with either a depth-first or a breadth-first search in time O(n). To find the lengths, just keep track of the lengths of the edges you've seen along the paths you've traveled as you travel them.
This is not different from "graph problems": a tree is a special case of a graph. Dijkstra's algorithm is a standard of graph traversal. Just modify it a little: keep all of the path lengths as you find them, and don't worry about the compare-update step, since you're going to keep all of the results. Continue until you run out of nodes to check, and there are your path lengths.

Finding the list of common children (descendants) for any two nodes in a cyclic graph

I have a cyclic directed graph and I was wondering if there is any algorithm (preferably an optimum one) to make a list of common descendants between any two nodes? Something almost opposite of what Lowest Common Ancestor (LCA) does.
As user1990169 suggests, you can compute the set of vertices reachable from each of the starting vertices using DFS and then return the intersection.
If you're planning to do this repeatedly on the same graph, then it might be worthwhile first to compute and contract the strong components to supervertices representing a set of vertices. As a side effect, you can get a topological order on supervertices. This allows a data-parallel algorithm to compute reachability from multiple starting vertices at the same time. Initialize all vertex labels to {}. For each start vertex v, set the label to {v}. Now, sweep all vertices w in topological order, updating the label of w's out-neighbors x by setting it to the union of x's label and w's label. Use bitsets for a compact, efficient representation of the sets. The downside is that we cannot prune as with single reachability computations.
I would recommend using a DFS (depth first search).
For each input node
Create a collection to store reachable nodes
Perform a DFS to find reachable nodes
When a node is reached
If it's already stored stop searching that path // Prevent cycles
Else store it and continue
Find the intersection between all collections of nodes
Note: You could easily use BFS (breadth first search) instead with the same logic if you wanted.
When you implement this keep in mind there will be a few special cases you can look for to further optimize your search such as:
If an input node doesn't have any vertices then there are no common nodes
If one input node (A) reaches another input node (B), then A can reach everything B can. This means the algorithm wouldn't have to be ran on B.
etc.
Why not just reverse the direction of the edge and use LCA?

Efficient way for finding the nodes having maximum degree of separation in a connected graph

I am working on a graph library.It has to have a function which finds the two nodes which are most separated i.e they maximum number of the minimum number of nodes required to traverse before reaching the target node from the source node.
One naive way would be to calculate the degree of separation from each node to all other node and repeat the same for every node.
The complexity of this turns out to be O(n^2).
Any better solution to this problem ?
Use Floyd-Warshall algorithm to find all pairs shortest path. Then iterate through results and find one with the longest path.
Without any assumptions on the graph, Floyd-Warshall is the way to go.
If your graph is sparse (i.e. it has a relatively few edges by node, or |E|<<|N|^2), then Johnson is likely to be faster.
With unit edge weight (which seems to be your case), a naïve approach by computing the furthest node (with BFS) for each node leads to O(|N|.|E|). This can probably be improved further, but I don't see a way right now.

Resources