I'm trying to apply Djikstra's algorithm on this graph from my textbook, but I keep getting stuck on vertex A when trying to traverse from G->C. Here is the link to the graph image:
LINK
I'll outline my steps below:
I start at the initial vertex(G).
A receives a cost of 6, E receives a cost of 1, H receives a cost of 4 since they are all initially infinity. G is marked as visited.
I go to the neighbor with the shortest cost; in this case its E.
At E, I set the cost of B as 1 + 2 = 3, and the cost of F as 1 + 2 = 3. E is then marked as visited.
I visit the neighbor of E with the lowest cost: This is where I start to get stuck since both B and F have the same cost. Assume that I choose B.
At B, I set the cost of C as 3 + 7 = 10 and the cost of A as 5.
Now A is the neighbor with the lowest cost but accessing it makes me stuck since I can't get out.
I'd really appreciate some suggestions or corrections if I am approaching it wrong.
Since G has already been marked as visited, this node is no longer considered and thus A is also considered, since there are no more possible connections.
At step 6 the nodes that have been visited are G, E and B. Now you have to pick the node with the minimum distance value, which is F. So the flaw in step 7 is really the assumption that it has to be a neighbour node.
Continuing from step 7:
Pick F. Update C's distance to 6. Mark F visited.
Pick H. Update D's distance to 6. Mark H visited.
Now pick A. No updates required. Mark A visited.
Pick C or D in any order and mark them visited as well. No updates required here.
Related
Question:
Given a graph of N nodes and M edges, the edges are indexed from 1 -> M. It is guaranteed that there's a path between any 2 nodes.
You need to assign weights for M edges. The weights are in the range of [1...M], and each number can only occur once.
To be shorted, the answer should be a permutation array of [1...M], in which arr[i] = x means edge[i] has the weight of x.
You are given a set R of n-1 edges. R is guaranteed to be a Spanning Tree of the graph.
Find a way to assign weights so that R is the Minimum Spanning Tree of the graph, if there are multiple answers, print the one with minimum lexicographical order.
Contraints:
N, M <= 10^6
Example:
Edges:
3 4
1 2
2 3
1 3
1 4
R = [2, 4, 5]
Answer: 3 4 5 1 2
Explaination:
If you assign weights for the graph like the above image, the MST would be the set R, and it has the smallest lexicographical order.
My take with O(N^2):
Since it asks for the minimum lexicographical order, I traverse through the list of edges, assigning the weights in an increasing order. Intially, w = 1. There can be 3 situations:
If edge[i] is in R, assign weight[i] = w, increase w by 1
If edge[i] is not in R: say edge[i] connect nodes u and v. assign weight and increase w for each edge in the path from u to v in R (if that edge is not assigned yet). Then assign weight and increase w for edge[i]
If edge[i] is assigned, skip it
Is there any way to improve my solution so that it can work in O(N.logN) or less?
Yes, there's an O(m log m)-time algorithm.
The fundamental cycle of a non-tree edge e is comprised of e and the path in the tree between the endpoints of e. Given weights, the spanning tree is minimum if and only if, for every non-tree edge e, the heaviest edge in the fundamental cycle of e is e itself.
The lexicographic objective lends itself to a greedy algorithm, where we find the least valid assignment for edge 1, then edge 2 given edge 1, then edge 3 given the previous edges, etc. Here's the core idea: if the next unassigned edge is a non-tree edge, assign the next numbers to the unassigned tree edges in its fundamental cycle; then assign the next number.
In the example, edge 3-4 is first, and edges 1-3 and 1-4 complete its fundamental cycle. Therefore we assign 1-3 → 1 and 1-4 → 2 and then 3-4 → 3. Next is 1-2, a tree edge, so 1-2 → 4. Finally, 2-3 → 5 (1-2 and 1-3 are already assigned).
To implement this efficiently, we need two ingredients: a way to enumerate the unassigned edges in a fundamental cycle, and a way to assign numbers. My proposal for the former would be to store the spanning tree with the assigned edges contracted. We don't need anything fancy; start by rooting the spanning tree somewhere and running depth-first search to record parent pointers and depths. The fundamental cycle of e will be given by the paths to the least common ancestor of the endpoints of e. To do the contraction, we add a Boolean field indicating whether the parent edge is contracted, then use the path compression trick from disjoint-set forests. The work will be O(m log m) worst case, but O(m) average case. I think there's a strong possibility that the offline least common ancestor algorithms can be plugged in here to get the worst case down to O(m).
As for number assignment, we can handle this in linear time. For each edge, record the index of the edge that caused it to be assigned. At the end, stably bucket sort by this index, breaking ties by putting tree edges before non-tree. This can be done in O(m) time.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
Given a Directed Weighted Graph which is Strongly Connected. I need to find a strongly connected sub-graph out of this graph such that the difference between the maximum and minimum weight edges is minimum.
To be more clearly, I need to get rid of edges in such a way that after removing them, the graph will still be strongly connected and the difference between the maximum and minimum weight edges is minimum.
Here is an example:
The first line is the number of N nodes and M edges of this graph. The next M lines represent the edges of this graph.
3 6
1 2 8
2 3 32
3 1 16
1 3 81
3 2 243
2 1 27
The chosen N-nodes sub-graph would contain the edges:
1 2 8
2 3 32
3 1 16
The difference between the maximum and minimum weight edges is: 32 - 8 = 24.
Which is minimum among all choices.
I'm looking for an optimal solution. There are at most 3000 nodes and 5000 edges.
Given an algorithm that tests whether a given digraph G = (V, E) is strongly connected in O(f(|V|, |E|)) time, this problem can be solved in time O(|E|*f(|V|, |E|)) -- and better than that if testing for strong connectivity can be done more quickly after adding or removing a single edge to an already-tested digraph.
Sort edges in increasing order by weight, and number them in this order. Initially, add the first (lowest-weight) edge to the set E' of selected edges; for as long E' is not strongly connected, add the next edge to it. If this loop does not terminate then G is not strongly connected. Otherwise, when it stops, after adding, say, edge j, we have found a minimum-difference solution given that we include edge 1. Record this (1, j) solution as the incumbent.
Now remove edge 1 from E', so that edge 2 is the lowest-weight edge remaining in E'. Leave all other already-decided edges in place, and begin adding the next-lowest-weight edges again, starting at edge j+1, until an SCG forms. This can be repeated to compute the minimum-difference solution given that the lowest-weight edge included is edge i, for each i <= |V|. Keep the best overall.
Note that when solving for the starting point i+1, it isn't necessary to get rid of the edges decided for the previous starting point i: If edges i, i+1, ..., j-1 do not form an SCG, then edges i+1, i+2, ..., j-1 do not form an SCG either. Exploiting this means the overall outer loop runs just |E| times, instead of O(|E|^2) times.
Can't Dijkstra's algorithm be implemented using a DFS that keeps track of the length of the current path traveled and every time it arrives in an unvisited node it updates the length of the shortest path to that node, and if the node arrived at is already visited, update the length if the current length is smaller than the length in the node?
Which is just DFS, meaning the run time should be linear ( O(|V| + |E|) ).
Let's take this graph as example, where the search should start in a, and the target node is c:
DFS
Assuming children of a node are traversed in their lexical order, a DFS will visit the nodes in the order a, b, c, d, e
It will find these distances:
a: 0
b: 5
c: 13
d: 8
Then from d it will see c again, and update it to 12
Next is:
e: 1
From e it will see b again, and update it to 3. But then a DFS falls short of also seeing the impact this change has on nodes c and d.
Dijkstra's
Dijkstra's algorithm, on the other hand, will visit nodes in this order:
a: 0
e: 1
b: 3
Then it will take the edge with weight 5, but see that b was already visited, and ignore it. Then:
d: 6
c: 10
... and the target was found with the correct distance.
BFS
Just to answer to your comment below: BFS will also not find the correct path, because BFS does not take the (total) weights into consideration; it just minimises the number of edges on a path.
BFS will visit the nodes like this:
a: 0
b: 5
e: 1
c: 13
... and it will stop there. If you would not stop, but continue (with potential overwriting), then the process continues:
d: 8
Then it sees b from e, and updates:
b: 3
However, as b was already visited, BFS will not see the impact this change has on c and d.
It also sees c from d and updates c to 12. Then there is nothing more to do for BFS, and clearly the result is wrong.
When you arrive at a visited node, called A, assume that the length of current path is shorter than the length in A, so you update length to A. But what about those nodes that connect with A? You need to update them too, but you can't, because A is already visited.
In short, the run time is linear, but the algorithm is incorrect.
I need help to solve this question :
you have undirected graph G=(V,E) you want to write an algorithm to adjust all
One of the edges, so that in the directed graph obtained, he number of incoming edges into the node be always greater than zero.
for all edge {u,v} ∈ E you should chose one direction (u,v) or (v,u).
When the answer is positive, the algorithm must return the intention of the edges - which fulfills the requirement
As was pointed out, this problem clearly does not always have a solution. Since every vertex must have at least one incoming edge, if we have E < V, the problem is impossible.
So, let's assume that we have E >= V. Here is one way to approach the algorithm: First, count the number of edges attached to each vertex in O(E) time. Note, my solution assumes appropriate storage like an adjacency list. Can you see why an adjacency matrix would have a worse complexity?
Second, we will make a binary minheap of the vertices, according to their corresponding edge count, in O(V). Some intuition: if we have a vertex with only one edge, we must convert that into an incoming edge! When we assign the direction of that edge, we need to update the edge count of the vertex on the other side. If that other vertex goes from 2 edges to 1, we now are forced to assign the direction of its one edge left. Visually:
1 - 2 - 1
Arbitrarily choose a 1 edge count to make directed
1 - 2 -> 0
2 just lost an edge, so update to 1!
1 - 1 -> 0
Since it only has 1 edge now, convert its edge to be incoming!
0 -> 0 -> 0
Obviously this graph doesn't work since V > E, but you get the idea.
So, V times, we extract the minimum from the heap and fix in O(logV). Each time, decrement the edge count of the neighbor. Assuming the adjacency list, we can find a neighbor (first element) and update the count in O(1), and we can fix the heap again in O(logV). Overall, this step takes O(V logV).
Note, if all of our remaining vertices have more than one possible edge, this approach will arbitrarily select one of the vertices with a smallest edge count and arbitrarily select one of its edges. I will let you think about why this works (or try to provide a counter-example if you think it doesn't!) Finally, if E > V, then when we finish, there may be extra unnecessary edges left over. In O(E) time, we can arbitrarily assign directions to those edges.
Overall, we are looking at V + V*logV + E aka O(E + VlogV). Hope this helps!
I start out with a graph of N nodes with no edges.
Then I procede to take M predetermined steps.
At each step, I must either create an edge between two nodes, or delete an edge.
After each step, I must print out how many connected components there are in my graph.
Is there an algorithm for solving this problem in time linear with respect to M? If not, is there one better than O(min(M,N) * M) in the worst case?
EDIT:
The program does not get to decide what the M steps are.
I have to read from the input, whether I am supposed to create an edge or delete it, and also which edge I am supposed to create/delete.
So example input might be
N = 4
M = 4
JOIN 1 2
JOIN 2 3
DELETE 2 3
DELETE 1 2
Then my output should be
3 # (1 2) 3 4
2 # (1 2 3) 4
3 # (1 2) 3 4
4 # 1 2 3 4
There are ways to solve this problem fully online, but they're more complicated than this answer. The algorithm that I'm proposing is to maintain a spanning forest of the available edges, together with the number of components of the spanning forest (and hence the graph). If we were attacking this problem fully online, then this would be problematic, since a spanning forest edge might get deleted, leaving us to paw through the unused edges for a replacement. We know, however, how soon each edge currently in the graph will be deleted.
The particular spanning forest that we maintain is a maximum-weight spanning forest, where the weight of each edge is its deletion time. If an edge belonging to this spanning forest is deleted, then there is no replacement, since every other edge connecting the components represented by its endpoints either hasn't been inserted yet or, having lesser weight, has already been deleted.
There's a dynamic tree data structure, also referred to as a link/cut tree, due to Sleator and Tarjan, that can be made to provide the following operations in logarithmic time.
Link(u, v, w) - inserts an edge between u and v with weight w;
u and v must not be connected already
Cut(u, v) - cuts the edge between u and v, if it exists;
returns a boolean indicating whether an edge was removed
FindMin(u, v) - finds the minimum-weight edge on the path from u to v
and returns its endpoints and weight;
returns null if either u = v or u and v are not connected
To maintain the forest, when an edge from u to v is inserted, compare its removal time to the minimum on the path from u to v. If the minimum does not exist, then insert the edge. If the minimum is less than the new edge, delete the minimum and replace it with the new edge. Otherwise, do nothing. When an edge from u to v is deleted, attempt to delete it from the forest.
The running time of this approach is O(m log n). If you don't have a dynamic tree handy, then it admittedly will take quite a while to implement. Instead of using a proper dynamic tree, I've had success with a much simpler data structure that just stores the forest as a bunch of nodes with weights and parent pointers. The running time then is O(m d) where d is the maximum diameter of the graph, and if you're lucky, d is quite a lot less than n.