How Topological Sort Works With DFS For The Below Graph - depth-first-search

5
^
|
3
^
|
1->2->4
For the above graph one of the topological sorts should be 1,3,2,5,4
But if I apply DFS algo(with temp stack) for topological sorting:
Start at 1.
Adjacent vertices are 3,2
Take 3 as next vertex
Adjacent vertex of 3 is 5
No adjacent for 5.
Add 5 into the temp stack.
Get back to 3 & add 3 to temp stack.
Take 2 as next vertex
Adjacent vertex of 2 is 4.
No adjacent for 4.
Add 4 to temp stack.
Get back to 2 & add 2 to temp stack.
Get back to 1 & add 1 to temp stack.
If I print the temp stack it would show 1,2,4,3,5.
What am I missing here? Please help me with the correct steps for better understanding this particular scenario.

Related

undirected acyclic graph edge insertion

Is there any algorithm that inserts a node in undirected graph iff graph is acyclic?
for example:
if graph is like below
0 - 1
|
2 - 3
4 - 5
valid insertion : 2-4
0 - 1
|
2 - 3
|
4 - 5
invalid insertion : 1 - 3
0 - 1
| | <=== cyclic!!!
2 - 3
4 - 5
If there is any example code with c++, I would really appreciate.
You can maintain a disjoint-set data structure for the set of vertices. This structure has the following operations:
find(x) to return the identifier of the set where x belongs,
union(x,y) to merge the sets of x and y.
Start with a set for the each vertex.
Before adding an edge, check whether its ends are in the same set.
If not, add the edge and merge the corresponding sets.
For your example, the state of the data structure is the following:
S1 = {0,1,2,3}
S2 = {4,5}
When you try to add an edge 1-3, you get that vertices 1 and 3 belong to the same set S1, so you skip adding.
When you try to add an edge 2-4, you get that vertices 2 and 4 belong to the different sets (S1 and S2, correspondingly), you add this edge, and update the structure to be:
S1 = {0,1,2,3,4,5}

binary tree compaction of same subtree

Given a tree, find the common subtrees and replace the common subtrees and compact the tree.
e.g.
1
/ \
2 3
/ | /\
4 5 4 5
should be converted to
1
/ \
2 3
/ | /\
4 5 | |
^ ^ | |
|__|___| |
|_____|
this was asked in my interview. The approach i shared was not optimal O(n^2), i would be grateful if someone could help in solutioning or redirect me to a similar problem. I couldn't find any. Thenks!
edit- more complex eg:
1
/ \
2 3
/ | /\
4 5 2 7
/\
4 5
whole subtree rooted at 2 should be replaced.
1
/ \
2 <--3
/ | \
4 5 7
You can do this in a single DFS traversal using a hash map from (value, left_pointer, right_pointer) -> node to collapse repeated occurrences of the subtree.
As you leave each node in your DFS, you just look it up in the map. If a matching node already exists, then replace it with the pre-existing one. Otherwise, add it to the map.
This takes O(n) time, because you are comparing the actual pointers to the left + right subtrees, instead of traversing the trees to compare them. The pointer comparison gives the same result, because the left and right subtrees have already been canonicalized.
Firstly, we need to store the node values that appear in a hash table. If the tree already exists, we can iterate the tree and if a node value is already in the set of nodes and delete the branches of that node. Otherwise, store the values in a hash map and each time, when a new node is made, check if the value appears in the map.

Given a set of possible starting nodes, find the smallest path that visits certain nodes and returns back

I have a set of nodes (<= 10,000) and edges (<= 50,000) which connect all of them with some combination. That is, you can visit any node starting from any other using atleast one combination of edges. The edges have their length defined.
I am supplied a set of mustpass nodes (maximum 5). All of them have to be visited, and we can pass through them multiple times if needed. We need to start our journey from one of the nodes which are not mustpass, visit all mustpass nodes, and return back to our initial node.
We need to find the shortest distance of such a path.
Say we have 5 nodes indexed 1, 2, 3, 4, 5 and the following edges in the format node -> node : length (all undirected):
1 -> 2 : 1
1 -> 5 : 2
3 -> 2 : 3
3 -> 4 : 5
4 -> 2 : 7
4 -> 5 : 10
And the mustpass nodes are 1, 2, 3. Our shortest distance can be achieved when we start from node 5, have a path as such: 5-1-2-3-2-1-5, and hence travel a distance of 12. 12 is our desired output.
Is there an efficient way to approach this?
Here`s O(E log V) solution:
Lets consider starting node as must-pass node
Using Dijkstra find shortest paths between all pairs of "must-pass" nodes
Now problem is reduced to Traveling Salesman Problem with 6 cities
We can either check all permutations in O(6!) time or use dynamic programming for O(2^6 * 6^2) either way since 6 is a constant complexity is O(1) for this part

Maximum path cost in matrix

Can anyone tell the algorithm for finding the maximum path cost in a NxM matrix starting from top left corner and ending with bottom right corner with left ,right , down movement is allowed in a matrix and contains negative cost. A cell can be visited any number of times and after visiting a cell its cost is replaced with 0
Constraints
1 <= nxm <= 4x10^6
INPUT
4 5
1 2 3 -1 -2
-5 -8 -1 2 -150
1 2 3 -250 100
1 1 1 1 20
OUTPUT
37
Explanation is given in the image
Explanation of Output
Since you have also negative costs then use bellman-ford. What you do is that you change sign of all the costs(convert negative signs to positive and positive to negative) then find the shortest path and this path will be the longest because you have changed the signs.
If the sign is never becoms negative then use dijkstra shrtest-path but before that make all values negative and this will return you the longest path with it's cost.
You matrix is a direct graph. In your image you are trying to find a path(max or min) from index (0,0) to (n-1,n-1).
You need these things to represent it as a graph.
You need a linkedlist and in each node you have a first_Node, second_Node,Cost to move from first node to second.
An array of linkedlist. In each array index you save a linkedlist.If for example there is a path from 0 to 5 and 0 to 1(it's an undirected graph) then your graph will look like this.
If you want a direct-graph then simply add in adj[0] = 5 and do not add in adj[5] = 0 , this means that there is path from 0 to 5 but not from 5 to zero.
Here linkedlist represents only nodes which are connected not there cost. You have to add extra variable there which keep cost for each two nodes and it will look like this.
Now instead of first linkedlist put this linkedlist in your array and you have a graph now to run shortest or longest path algorithm.
If you want an intellgent algorithm then you can use A* with heuristic, i guess manhattan will be best.
If cost of your edges is not negative then use Dijkstra.
If cost is negative then use bellman-ford algorithm.
You can always find the longest path by converting the minus sign to plus and plus to minus and then run shortest path algorithm. Path founded will be longest.
I answered this question and as you said in comments to look at point two. If that's a task then main idea of this assignment is ensure the Monotonocity.
h stands for heuristic cost.
A stands for accumulated cost.
Which says that each node the h(A) =< h(A) + A(A,B). Means if you want to move from A to B then cost should not be decreasing(can you do something with your values such that this property will hold) but increasing and once you satisfy this condition then everyone node which A* chooses , that node will be part of your path from source to Goal because this is the path with shortest/longest value.
pathMax You can enforece monotonicity. If there is path from A to B such that f(S...AB) < f(S ..B) then set cost of the f(S...AB) = Max(f(S...AB) , f(S...A)) where S means source.
Since moving up is not allowed, paths always look like a set of horizontal intervals that share at least 1 position (for the down move). Answers can be characterized as, say
struct Answer {
int layer[N][2]; // layer[i][0] and [i][1] represent interval start&end
// with 0 <= layer[i][0] <= layer[i][1] < M
// layer[0][0] = 0, layer[N][1] = M-1
// and non-empty intersection of layers i and i+1
};
An alternative encoding is to note only layer widths and offsets to each other; but you would still have to make sure that the last layer includes the exit cell.
Assuming that you have a maxLayer routine that finds the highest-scoring interval in each layer (const O(M) per layer), and that all such such layers overlap, this would yield an O(N+M) optimal answer. However, it may be necessary to expand intervals to ensure that overlap occurs; and there may be multiple highest-scoring intervals in a given layer. At this point I would model the problem as a directed graph:
each layer has one node per score-maximizing horizontal continuous interval.
nodes from one layer are connected to nodes in the next layer according to the cost of expanding both intervals to achieve at least 1 overlap. If they already overlap, the cost is 0. Edge costs will always be zero or negative (otherwise, either source or target intervals could have scored higher by growing bigger). Add the (expanded) source-node interval value to the connection cost to get an "edge weight".
You can then run Dijkstra on this graph (negate edge weights so that the "longest path" is returned) to find the optimal path. Even better, since all paths pass once and only once through each layer, you only need to keep track of the best route to each node, and only need to build nodes and edges for the layer you are working on.
Implementation details ahead
to calculate maxLayer in O(M), use Kadane's Algorithm, modified to return all maximal intervals instead of only the first. Where the linked algorithm discards an interval and starts anew, you would instead keep a copy of that contender to use later.
given the sample input, the maximal intervals would look like this:
[0]
1 2 3 -1 -2 [1 2 3]
-5 -8 -1 2 -150 => [2]
1 2 3 -250 100 [1 2 3] [100]
1 1 1 1 20 [1 1 1 1 20]
[0]
given those intervals, they would yield the following graph:
(0)
| =>0
(+6)
\ -1=>5
\
(+2)
=>7/ \ -150=>-143
/ \
(+7) (+100)
=>12 \ / =>-43
\ /
(+24)
| =>37
(0)
when two edges incide on a single node (row 1 1 1 1 20), carry forward only the highest incoming value.
For each element in a row, find the maximum cost that can be obtained if we move horizontally across the row, given that we go through that element.
Eg. For the row
1 2 3 -1 -2
The maximum cost for each element obtained if we move horizontally given that we pass through that element will be
6 6 6 5 3
Explanation:
for element 3: we can move backwards horizontally touching 1 and 2. we will not move horizontally forward as the values -1 and -2, reduces the cost value.
So the maximum cost for 3 = 1 + 2 + 3 = 6
The maximum cost matrix for each of elements in a row if we move horizontally, for the input you have given in the description will be
6 6 6 5 3
-5 -7 1 2 -148
6 6 6 -144 100
24 24 24 24 24
Since we can move vertically from one row to the below row, update the maximum cost for each element as follows:
cost[i][j] = cost[i][j] + cost[i-1][j]
So the final cost matrix will be :
6 6 6 5 3
1 -1 7 7 -145
7 5 13 -137 -45
31 29 37 -113 -21
Maximum value in the last row of the above matrix will be give you the required output i.e 37

How to sort each link in linked list representation of a graph optimally?

Like graph in form of a list :
1 : 2 -> 3
2 : 3 -> 4 -> 1
3 : 2 -> 1 -> 4
4 : 3 -> 2
whew 1 : 2 -> 3 means that node 1 is connected to nodes 2 and 3.
So the output should be each node list sorted :
1 : 2 -> 3
2 : 1 -> 3 -> 4
3 : 1 -> 2 -> 4
4 : 2 -> 3
So, this can be done in n * O(log n) time by sorting each list, but what is the most optimal algorithm for this problem ?
Sorting all separate lists would be easiest way to get what you want. However, if you have n nodes, you have to sort n lists. Each list could have n-1 entries. Sorting 1 list of n-1 entries would have complexity O(n*log(n)). Your total complexity would be O(n²*log(n)).
You could try to go under that by sorting your lists sequentially and exploiting that information. From your example i assume that your graph is undirected, which allows for the following optimization.
An example first:
You start by sorting the first list which would here yield 2->3.
Then your first list would be done. You could then add '1' to the
lists of node 2 and 3 (as 1 will appear in their lists as first
item). This would give you the start of those lists. Then you move
on to the list of node 2.
Seeing as you already know the start of it
(1), you could skip all that node during sorting. You could do a
quick pass through your linked list and remove 1 from the set. Then
you sort the rest (which would give 3->4) and append it to the 1 you
already had. As with 1, you now have the full sorted list of 2 and
you can add '2' to the list of 3 and 4.
You then continue for 3, do a quick pass to remove all nodes you already know, and sort the
rest. This would give you 4 and you append that to what you already have to get 1->2->4. Add 3 to the list of node 4.
The list of node 4 is already done as there are no nodes in the list with id >4.
More formally:
initialize the final sorted list of every node to null;
for(i=1;i<=nrNodes;i++){
remove all nodes with id<i from linked list;
A:=sort remainder of list
append A to the final sorted list of i;
for (every node n in A){
append i to final sorted list of node n
}
}
This should be faster than sequentially sorting all the lists as the lists to be sorted are smaller.

Resources