Feedback on algorithm for Steiner Tree with restrictions - graph-algorithm

For an assignment, I have to create a Steiner Tree. However, this is not a typical Steiner Tree, as the graph structure we're required to use does not allow insertion of new vertices. Rather, the test cases define a graph structure of N vertices and M edges while specifically marking X vertices as target nodes. These are the nodes we have to span while using some, none or all of the unmarked vertices in the graph.
My solution to this problem is
Implement Dijkstra's Algorithm to find the shortest path between all the target vertices
For each of the shortest paths 1:n
Extract all current selected path vertices into a set
Extract all remaining vertices into a set
For all vertices of the current selected path 1:m
Execute Dijkstra to find shortest path between current vertex and other path's vertices
If this creates a spanning tree, save path and length in priority queue sorted by length value
Pop top of priority queue and return path
My issue is that this is an exhaustive search that uses the initial application of Dijkstra to create a reduced set of possible start-end vertices for a shorter path than a minimum spanning tree.
Is there a heuristic or other algorithm that may solve this problem?

With some help, I worked out this answer for a similar problem that I had. Rather than adding new vertices as in a spacial steiner tree problem, the new steiner points in this graph are the vertices that lie along the path between the marked nodes. For a graph with N vertices, M edges, X require vertices, and S found vertices (vertices along our path):
Compute All Pairs Shorest Paths (Floyd-Warshall, Johnson's, whatever)
for k in X
remove k from X, insert k into S
for v in (X + S) - Both sets
find the shortest distance from k to v - path P
for u in P (all vertices on the path)
insert u into S
if u exists in k, remove u from k
Now for the wall of text as to what this algorithm does. We pick a vertex k in X, and then find the minimum distance to the nearest other vertex in the target set X, or in the result set S, and call it v. Then we follow the path of nodes from {k,u}, inserting them into our result set. Finally, double check and make sure that any vertices in X that were on the path (shouldn't happen) are removed from X.
Any new vertex that you want to add, c, will have a minimum distance to some node already in your result set S. Since the nodes already in S are the minimum distance apart, it follows that c will be the minimum distance from any point in S to c. For example, if you have three nodes, A, B, and C, if A and B are already found to be a minimum distance apart, adding C fulfills the requirement that it is the minimum distance from B, and the minimum distance path from A to C goes through B.
I did some research on the discrete Steiner Tree problem (which is what this is), and this is the best brute force solution that I found. The main problem is going to be the O(n^3) time it takes to do all pairs shortest paths, but then the construction of the minimum tree should be straightforward and quick, since you just need to look up distance information. The implementation I wound up working with is outlined nicely on wikipedia.

Related

Reduction - Subset sum problem to path sum problem

I am trying to reduce the decision subset sum problem to decision path sum problem but I can not see the relation between them.
The subset sum problem is about deciding if there is a subset in the set S where the subset sum equal k.
The path sum problem is about deciding if there is a path from point (1,1) to point (n,n) in a nxn grid where the path sum equal k. The path can be created by moving from (i, j) to either (i+1, j) or (i,j+1) but at one and only one step during the movement, you can go back to the place it just came from.
Notes: All the integers are poistive integers.

a new edge is insert to a Minimum spanning tree

I trying to find an algorithm to the following question with one different :
the edge are not distinct.
Give an efficient algorithm to test if T remains the minimum-cost spanning tree with the new edge added to G.
in this link- there is a solution but it is not for the different I wrote up:
the edges are not nessecerliy distinct.
Updating a Minimum spanning tree when a new edge is inserted
someone has an idea?
Well, the naive approach of just using Prim or Kruskal to find the min cost spanning tree of the new graph and then see which one has a lower total cost isn't too bad at O(|E|log|E|).
But we don't need to look at the whole graph.
Suppose your new edge connects vertices A and B. Let C be the parent of A. If B is not a descendent of A, then if A-B is lower cost than A-C, then T is no longer the MST and B should be the new parent of the subtree rooted at A.
If B is a descendant of A, then if A-B is shorter than any of the branches in T along the path from A to B, then T is no longer the MST, and the highest cost edge along that path should be removed, B is the root of the newly disconnected component, and should be added as a child of A.
I believe you may need to check these things a second time, reversing which vertices are A and B. The complexity of this is log|V| where the base of the log is the average number of children per node of T. In the case of T being a straight line, it's O(|V|), but otherwise, I think you could say it is O(log|V|).
First find an MST using one of the existing efficient algorithms.
Now adding an edge (v,w) creates a cycle in the MST. If the newly added edge has the maximum cost among the edges on the cycle then the MST remains as it is. If some other edge on the cycle has the maximum cost, then that's the edge to be removed to get a tree with lower cost.
So we need an efficient way to find the edge with the maximum value on the cycle. You can climb from v and w until you reach LCA(v, w) (the least common ancestor of v and w) to get the edge with the max cost. This takes linear time in the worst case.
If you are going to answer multiple such queries then pre-processing the MST is probably better. You can pre-process the MST to get a sparse table data structure in O(N lg N) time and then use this data structure to answer max queries in O(lg N) time in the worst case.

Graph Algorithm : Similar to TSP

I want to solve a problem similar to the TSP( Travelling Salesman Problem).
I have N ( N > 0, N < 20 ) nodes and i must visit all nodes.
The cost between nodes are equal.
I can visit a node unlimited times.
I want to find more than one path and the cost have not restriction.
Tell me some effective algorithms about this problem?
Here is a solution that works with a weighted graph.
First, the naive solution, enumerating.
It works in O(n!) because there are (n-1)! Hamiltonian paths, and you need O(n) to check each one.
There is better algorithm, with dynamic programming in O(n*2^n)
Define the state as the following: for x a node, and S a set of nodes containing x:
w[S][x] = the weight of the shortest path that start at node x, and goes through all the node in the set S, and then finishes at 0.
Note that 0 does not necessarily belongs to S.
S = {x} is the basic case: w[S][x] = weight(w,0)
Then the recursion formula:
If S is larger than, {x}, Iterate over the possible next step y
w[S][x] = min(weight(x,y) + w[S\x][y] for all y in S\x)
This algorithm will output just one optimal path.

How to design an O(m) time algorithm to compute the shortest cycle of G(undirected unweighted graph) that contains s?

How to design an O(m) time algorithm to compute the shortest cycle of G(undirected unweighted graph) that contains s(s ∈ V) ?
You can run a BFS from your node s as starting point, this will give you a BFS-tree. Afterwards you can built a lowest-common-ancestor (LCA) data structure on this BFS-tree. This can be done for example with Tarjan's lowest-common-ancestor algorithm. I will not got into details here. Given two nodes v and w, LCA lets you find the lowest node in a tree (the BFS-tree in our case) that has v and w as descendents. The idea is when you are considering two nodes that are connected in our BFS-tree you want to check if their paths to the root (s is this case) + the edge that connects them forms a cycle (with s). This is the case if their LCA is s.
Assuming you have built the LCA, you run a second BFS. When expanding the neighbours of a node v, you also take into consideration the nodes already marked as explored. Suppose x is a neighbour of v such that x has already been explored. If the LCA of v and x is s then the path from x to s and form v to s in the BFS-tree plus the edge xv forms a cycle. The first x and v that you encounter in your second BFS gives you the desired result. If no such x exist then s is not contained in any cycle.
The cycle is also the shortest containing s.
The two BFS run in O(m) and the LCA construction can also be done in linear time, hence the whole procedure can be implemented in O(m).
This might a bit overkill. There surely is a much simpler solution.

Decide Whether All Shortest Paths From s to t Contain The Edge e

Let G = (V;E) be a directed graph whose edges all have non-negative weights. Let s,t be 2 vertices in V, and let e be an edge in E.
Describe an algorithm that decides whether all shortest paths from s to t contain the edge e.
Well, this is how you can achieve Dijsktra's time complexity:
Simply run Dijkstra from s and calculate delta(s,t) (the weight of the shortest path from s to t).
Remove the edge e, and run Djikstra again from s in the new graph.
If delta(s,t) in the new graph has increased, it means that all shortest paths from s to t contain the edge e, otherwise it's not true.
I was wondering whether there is a more efficient algorithm for solving this problem. Do you think that it's possible to beat Dijkstra's time complexity ?
Thanks in advance
Your approach sounds correct to me. You just calculate the shortest path with and without the possibility of taking edge e. That gives you 2 Dijkstra searches.
There is room for improvement if you go to A*, bidirectional search or recover your Dijkstra search tree:
A* would speed up your Dijkstra-query but it might not be possible for your graph as you need to be able to define a good bound on your remaining distance.
bidirectional search could be done with both searches meeting around the edge. You can then examine all paths with and without the edge with only 1 fast bidirectional query+ some extra work for both cases instead of having 2 full Dijkstra's that are very similar
you could search once without the edge and maintain your search tree. Then you add e and update the shortest path tree starting from the start point of e. If the label of the end point > the label of the start point + length e, the end point can be reached faster when using e. Recursively search the neighbours of your end point and only update the distances if they could be reached faster than before. Should save you some work.

Resources