A algorithm problem - algorithm

I want to design a algorithm. In a directed graph G=(V,E), and each arc has a numerical weight. The algorithm needs to return a set S of arcs of maximum weight so that no two arcs in A have the same tail. Assume that it has at least 7 nodes and 10 arcs. Could anyone give some hints about this algorithm?

You say that your arcs are not allowed to have the same tail. So I would divide the set of arcs into several "bins" which are determined by the tail of the arc. I.e. you take each arc, look at its tail, and put it into the corresponding bin.
Consider the graph consistign of the following arcs:
(1->2)
(1->3)
(2->1)
(2->4)
(3->2)
Then, we have something as follows:
bin 1 | 2 | 3 | 4
arc 2 3 | 1 4 | 2 | (empty)
weight .. .. | .. .. | .. |
It is now clear, that we can take at most one arc from each bin. In order to maximize the sum, we can pick always the one with the largest weight in each bin.
Edit: Note that your algorithm does not need to do this whole bin-thing. It can just walk across all arcs and update the solution dynamically.

Related

Algorithms. Single source shortest paths. Dijkstra's algorithm

How do I find all possible shortest paths from a source vertex to more than one destination, such that the edge-weights in the shortest paths tree are in decreasing order of weights?
Let us assume here a strict decreasing of the weights among a path.
This implies that when considering a given path, we have to memorize/consider not only the corresponding total distance, but also the value of the last weight.
Therefore, at a given node, we have to memorize different possible paths, i.e. different pairs (total distance, last weight), and not only one. This does not not mean that all combinations must be memorized. For example, if we have two paths (13,2) and (15,2), only (13,2) is kept. In the same spirit, if we get (10,3) and (10,2), only (10,3) must be kept.
This is illustrated in figure hereafter, hopefully self explaining. I assume directed edges here.
3 4 2
A(3,3) -->C (6,2), (11,5)---->D (11,4), (13,3) ------>F (13,2)
| | | NB: (15,2) skipped
|3 |5 |3
| | 4 |
S ------->B (6,6)------------>E (10, 4)
6
In practice, existing short path finding algorithms should be adapted for that. My understanding is that for example the Floyd–Warshall algorithm
can be adapted for that purpose.

Algorithm to 'trim' a graph

I am trying to create an algorithm to calculate the total resistance for a given an undirected graph with weighted edges. The algorithm will also be given a starting node and an ending node, which will represent the terminals connected to the power supply. For example, the graph on the top with starting node 1 and ending at node 6 will represent this circuit
(3)
|
|6
3 |
(2)------(4)
| |
|5 |1
| |
| 3 | 1
(1)------(5)------(6)
As you would realize, the 6 ohm resistor doesn't really matter in this context as current wouldn't flow through it if a voltage was applied between nodes 1 and 6. So, I figured that I should first of all 'trim' this graph. Here is the explanation of this process:
Trimming a graph is basically cutting off the parts of the graph which cannot be contained in a path between the starting node and the ending node which passes over any node at most once.
4 4
| /|
| / |
2--3 2--3 2--3
| | | | | |
| | | | | |
1--5--6 1--5--6 1--4--5
(1) (2) (3)
For example, in graph (1), node 4 should be trimmed because in any path between 1 and 6, visiting node 4 means visiting node 3 at least twice as there is no path from node 4 which doesn't visit node 3 again. If this graph is trimmed, it will become graph (3). However, if graph (2) is trimmed, it won't change because all nodes can be visited on a path from 1 to 6, including node 4.
So, how can I devise an algorithm that trims a graph with given starting and ending nodes?
EDIT: So, I have learned about the maxflow / mincut problem, and it seems like this could be used for the solution of this problem. I haven't tried it yet, but I will post another edit if I can manage to do it using flows.
Find the tree of Biconnected components.
Any node that is not on the path from s to t in the tree (or part of the component that is on the path) can be removed.
The time complexity is linear.
Biconnected component: https://en.wikipedia.org/wiki/Biconnected_component
Just remove all nodes with only one edge (not counting for the two ending nodes).
But this does not account for the nodes "beyond" the ending nodes. If in your original graph we want to calculate the resistance between nodes 5 and 6 then we do not need any other node (nodes 1, 2, 3 and 4 are all irrelevant).
To remove really all nodes that are irrelevant you have to find all different paths between the two ending nodes, and remove all nodes that are not part of any of those paths.
This can be a possible solution for this:
If starting from a node (say v) if we can reach both the source and terminal nodes with no vertices in common then that node has to be considered for the calculation of the total resistance.
By this I mean, suppose one of the path from v to source is (v, a1, a2, a3, a4, ..., source)
And the path from v to terminal be (v, b1, b2, b3, ..., terminal)
Then if the intersection of these gives zero elements, then the node v can not be trimmed. Otherwise it can be left out.
So we can have the following two solutions for this:
1. Do a depth-first search from each vertex and check if the paths have some common vertex or not.
Find all the bridges in the graph. You can look for it here: https://en.wikipedia.org/wiki/Bridge_(graph_theory)
The way to find all the bridges in a graph is given here: https://www.geeksforgeeks.org/bridge-in-a-graph/
If after removing a bridge-edge, the source and terminal vertices are in the same connected component then all the nodes on the other side of connected component can be trimmed from the graph.
For example: In the graph (1), there is only one bridge 3-4.
If we remove that we get two connected components (1,2,3,5,6) and (4). We can see that both 1 and 6 are in the same connected component, hence all other connected component nodes (here only node numbered 4) can be trimmed.

How to find 4 non intersecting spanning trees in 2D Torus

In my implementation I need to find 4 non intersecting spanning trees in a 2D torus. Assuming all the links are bidirectional. and Bidirectional links are not intersecting.
Ex: my 2D torus is of 3 * 3
| | |
--0-1-2--
| | |
--3-4-5--
| | |
--6-7-8--
| | |
So, each link here is actually representing a bidirectional link for example there are two edges between 0 and 3. one from 0 towards 3 and one from 3 towards 0.
In output I should get 4 non intersecting spanning trees.
Although I have thought of some algorithm but it fails somehow.
ALgorithm:
I have the torus represented in the form of adjacency matrix. And a link between 0 and 3 are represented by 1 in adjacency matrix at position AM[0][3] and AM[3][0]
Node consist of (node_number, parent,weight)
Intially I maintain a priorList in which all nodes are set to their (node_number, -1, INT_MAX) but root of spanning tree which is set to (node_number, -1, 0)
Extract node from priorList with minimum weight, such that its parent does not have already a child. (In first iteration it would always be root). This I do by checking in the set of already extracted nodes in MST.
If found then update all its neighbours other than the nodes already extracted from priorList.
here by updating I mean update their parents, if already discovered.
Now add the extracted node in 1st step into the MST.
Go to step 1 until priorList is not empty.
It will give 1 MST but will get stuck while getting the 2nd MST from the same Adjacency matrix which was left as output while calculation of 1st MST(By which I mean if I had already used some edges in the 1st MST then I would have removed that edges from the Matrix).
Remember all 4 spanning trees should start from the same given root, and try if I can somehow use variant of Prim's algorithm(http://en.wikipedia.org/wiki/Prim%27s_algorithm).
I don't know any other algorithm as of now, but lets see if someone can help.

Trying to understand how Dijkstra's algorithm works via a simple example

I want to get from a to d via the shorter route (lowest cost)
1 15
a--->b---->d
| /\
|2 /
| /1
| /
| /
| /
| /
| /
| /
\/
c
a can go to b at a cost of 1 or c at a cost of 2.
b can go to d at a cost of 15.
c can go to d at a cost of 1.
Wouldn't the algorithm start with a->b because it has a cost of 1 versus a->c which has a cost of 2? But then it can only go from b->d at a cost of 15 which is more costly than if it had gone from a->c->d
I'm trying to freshen up on this algorithm so please tell me if my logic is flawed.
In the first step the tentative distances of nodes from 'a' are found, which are s(b)= 1 and s(c) =2
Queue --> s(b) = 1, s(c) = 2
Now dequeing the priority queue we get b, so calculating tentative distances again s(d)= 16
Queue --> s(c) = 2, s(d) =16
Now dequeing we get c, so calculating tentative distances from c, s(d) =3 > previous value s(d)=17
So the shortest distance is 3
Mistake is think "the first way, the best way", it isn't true. In this algorithm you can update the cost of reaching to vertex (if it is warranted by lower cost).
Nodes are divided into visited, unvisited, available, unavailable.
We can don't think about visited, because if, he had the smallest value, and we haven't negative-value edge (see algorithm assumptions) you can't find better way.
Unvisited are all another, possible that we can't actually walk to all of them.
Available vertices are all unvisited, which we can visit now. (Unavailable is obvious, I think.)
At start available is only first vertex. We can follow a simple pattern.
Step by Step:
-Take the least expensive vertex from all (actually) available. This should be done by the priority queue. The simplest solution is a binary heap (O(|E| log |V|)), but if you thinking about performance, you can use Fibonacci heaps (O(|E|+|V|log|V|)), if don't, possible, but not recommended means is to use an array (O(|V|^2+E)). This should be the root.
-For the current node you should update all unvisited neighbours (unvisited, no unavailable (why, see above)) trip costs if( (cost of the current node + weight of the edge connecting them, with a neighbour) < (actual cost of reaching the neighbour, from the beginning node) ). When you changing unavailable to available, you must add changed elements to the priority queue. When you update a cost of node, you should upgrade heap, do not forget.
-Mark actually node as visited. Remove him from the priority queue (permanently, it's visited), in minimum-heap it's delete_root operation.
-Repeat until the queue isn't empty.
On your example it could look like this:
Number - actually the lowest total weight of path between nodes (first and last).
Stars - node is visited, this cost never changes.
Dash - node is not available in this moment.
| a | b | c | d |
-----------------
| 0 | - | - | - | <-- Available is only a.
-----------------
|*0*| 1 | 2 | - | <-- You can go to b and c.
-----------------
|*0*|*1*| 2 | 16| <-- b was cheaper, you updated costs from this vertex.
-----------------
|*0*|*1*|*2*| 3 | <-- You didn't stop, and find less costly way!
-----------------
|*0*|*1*|*2*|*3*| <-- Work done, the last vertex visited.
-----------------
More specifically, initially available is only first element, so at the beginning you must visit him. When it's done, available are two new nodes, and you should visit cheapest (from available, not visited). It's b. From b is the only way to d, so you upgrade only his cost (now d is available, but actual way (cost) may not be the optimal). Again take the cheapest vertex from available. It's c, because a and b are visited and 2 is smaller than 16. When you check this node you find better way to d, so you should update cost of d from 16 to 3. Visited last node (d) is formal and insignificant move. You visited all vertices, now your job is done.
Every time the algorithm visits a node, it puts all its neighbors (that aren't visited already) into the priority queue. The priority queue keeps the elements sorted by least cost, so that the shortest distance is always calculated first.
So to answer your question, it goes from a->b, then a->c, then b->d, then c->d.
If you want to speed up the algorithm, I suggest you implement the algorithm with binary heaps. Essentially what it does is it always tests the next lowest possible cost node with a very basic search.
http://algorithms.soc.srcf.net/notes/dijkstra_with_heaps.pdf

Least number of rides

I'm trying to solve this problem using an algorithm for at least a week but to no avail. I have a set of roads (1,2,3,...) and for each road there can be at least 1 vehicle that can pass (A,B,C,...). My problem is how to get the least number of rides for one to take to reach one road to another. For example:
road | vehicle(s)
1 | A,B
2 | A,B,C
3 | C,D
4 | C,D
5 | D,E
The output should be:
from 1, ride A or B to 2
from 2, ride C to 4
from 4, ride D to 5
The policy here is to exhaust one ride as much as possible, but the output should have the least number of ride changes.
Example 2:
road | vehicle(s)
1 | A,B
2 | A,B,C
3 | C,D
4 | C,D
5 | A,E
6 | E,F
7 | F
8 | F,H
9 | F,G
10 | F,G
11 | F
12 | F,G
13 | G,H
14 | H
Output:
from 1, ride A to 5
from 5, ride E to 6
from 6, ride F to 8
from 8, ride H to 14
Please help me to write the algorithm for the problem. I need to solve this for my project. Thanks!
PS: If you need other examples or clarification, just tell me in the comments below.
One way to think about this problem is to model it as a graph search problem. For each of the different vehicles v, construct a graph Gv whose nodes are all of the roads in the network with arcs between the nodes that are connected by vehicle v. For example, in your first example, the graph GA would have five nodes, of which there is only a connection from node 1 to node 2, while the graph GC would have five nodes with edges from 2 to 3, 3 to 4, and 4 to 2.
Now, consider the final graph G constructed as follows. G is formed by taking all of the graphs Gv for all of the vehicles v (meaning that there are multiple copies of each node in the original graph), then adding edges between corresponding nodes in the different graphs if there are multiple different vehicles that all reach a road. For example, in the graph G for the original problem, you would have G contain subgraphs GA and GB, ..., GE. Since road 1 is serviced by both vehicles A and B, you would add an edge between the nodes for road 1 in the graphs GA and GB, and since road 2 is serviced by vehicles A, B, and C, there would be edges connecting all of the road 2 nodes for subgraphs GA, GB, and GC.
You are interested in minimizing the number of transfers you need to make, and so we'd like to set up some costs in this graph that measure that. In particular, we say that any edge contained completely in one of the subgraphs Gv has cost zero, since once you're on a vehicle of a given type you don't need to make any changes to move around the roads the vehicle services. However, we assign a cost of one to each of the edges linking the subgraphs for different vehicles, since following this sort of edge would mean that you're changing which vehicle you're using. If you now trace out any path in this graph, the total cost of that path is the number of vehicle changes you make.
To finalize the construction, we need to have some way of finding a cost from the starting road to the destination. To do this, we'll add two new nodes s and t to the graph representing the start and end of the journey. Node s will have cost-zero directed edges to the first road of each of the subgraphs, since when you start off the journey you can pick any of the vehicles as your first step. Similarly, every subgraph's node for the final road will have a zero-cost edge to t, since once you arrive at the destination road it doesn't matter what vehicle you're in.
In this setup, any path from s to t has a cost equal to the total number of transfers you need to make. Finding the shortest path in this graph from s to t therefore gives you both the route to take and the cost of that path. You can solve this using Dijkstra's algorithm, for example.
The runtime of this algorithm isn't stellar, but it's still polynomial time. Suppose that there are n roads and m different vehicles. The graph we create will have m different subgraphs in it, each of which is for one vehicle, and in the worst case these graphs have O(n2) edges in them. If we then link together all the corresponding nodes of these subgraphs where you can change lines, then in the worst case there will be O((mn)2) such edges, since there are m graphs of n nodes that all might be connected to one another. We thus have a graph with O(mn) nodes and O((mn)2) edges, so we can run Dijkstra's algorithm in O((mn)2 + mn log mn) time.
The main idea that I think is important to take away from this problem is that you can often solve problems about finding paths in graphs subject to certain constraints by creating a new graph formed out of multiple copies of the old graph and then coming up with a good edge-cost function for that graph.
Hope this helps!

Resources