Shortest route modification - c++

Is there a way to modify this to show the route of the shortest path? For example, if i had a list of numbers like (3,1),(3,0),(4,3),(2,1) the output for getting from 4 to 1 would be 4->3,3->1
// Prints shortest paths from src to all other vertices
void Graph::shortestPath(int src)
{
// Create a priority queue to store vertices that
// are being preprocessed. This is weird syntax in C++.
// Refer below link for details of this syntax
// http://geeksquiz.com/implement-min-heap-using-stl/
priority_queue< iPair, vector <iPair> , greater<iPair> > pq;
// Create a vector for distances and initialize all
// distances as infinite (INF)
vector<int> dist(V, INF);
// Insert source itself in priority queue and initialize
// its distance as 0.
pq.push(make_pair(0, src));
dist[src] = 0;
/* Looping till priority queue becomes empty (or all
distances are not finalized) */
while (!pq.empty())
{
// The first vertex in pair is the minimum distance
// vertex, extract it from priority queue.
// vertex label is stored in second of pair (it
// has to be done this way to keep the vertices
// sorted distance (distance must be first item
// in pair)
int u = pq.top().second;
pq.pop();
// 'i' is used to get all adjacent vertices of a vertex
list< pair<int, int> >::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i)
{
// Get vertex label and weight of current adjacent
// of u.
int v = (*i).first;
int weight = (*i).second;
// If there is shorted path to v through u.
if (dist[v] > dist[u] + weight)
{
// Updating distance of v
dist[v] = dist[u] + weight;
pq.push(make_pair(dist[v], v));
}
}
}
// Print shortest distances stored in dist[]
printf("Vertex Distance from Source\n");
for (int i = 0; i < V; ++i)
printf("%d \t\t %d\n", i, dist[i]);
}
Putting in an array that stores the numbers of the path like 4,3,3,1 (using above example) seems like the best idea but i don't know where to insert the array in this code to do that.

Just as you save the distances for each vertex in the dist vector, save the predecessor vertex that last updated it in a vector called predecessor.
vector<int> dist(V, INF);
vector<int> predecessor(V, 0);
Then whenever you update the distance, update the predecessor:
dist[v] = dist[u] + weight;
predecessor[v] = u;
Finally, you can trace for any vertex the shortest path (Backward) to the source:
printf("Vertex Distance from Source shortest path from source\n");
for (int i = 0; i < V; ++i)
{
printf("%d \t\t %d\t\t", i, dist[i]);
int j = i;
do
{
printf("%d,", j);
j = predecessor[j];
} while(j != src);
printf("\n");
}

Sounds like a homework problem.
Your idea to store the numbers of the path would be great, if this were a DFS. Unfortunately, Djikstra's algorithm doesn't naturally keep track of the path like a DFS does; it simply takes the next closest node and updates the distance values. It's probably more similar to a BFS in that regard.
What you could do is as you update the distances to each node, somehow store which node you're coming from (maybe in your iPair struct if you're allowed to, maybe in a map/array if you have a way to ID your nodes). I'll call it a "from" reference for the sake of this post. Then, each time you find a shorter path to a node, you can also update that from reference.
How do you find the path to a given node then? Simple: just start at the end node, and follow the "from" references back to the source.

Related

Difference between range-based for loop and normal for loop Depth-First Search implementation

I'm trying to implement a depth first search algorithm for a graph data structure and my function looks like this:
void dfs(int x, vector <v_Int>& Adjacency_List, v_Int& visited) {
visited[x] = 1; //Mark current vertex as visited
for (int i = 0; i < Adjacency_List[x].size(); i++) { //Iterate through all neighbours of vertex x
if (visited[i] != 1) { //If neighbour not visited, recursively go there
dfs(i, Adjacency_List, visited);
}
}
}
When I used a normal for loop like I did above, the visited array does not get updated beyond the first vertex of the graph when I call the function dfs(0, Adjacency_List, visited);
However, when I change the normal for loop to a range based for loop like so:
for (auto &v : Adjacency_List[x]) { //Iterate through all neighbours of vertex x
if (!visited[v]) {
dfs(v, Adjacency_List, visited); //If neighbour not visited, recursively go there
}
}
The visited array gets updated accordingly whenever the dfs function is called. I'm not too sure why the 2nd implementation works but my initial implementation doesn't since both implementations seem to have similar logics. Thank you for your help!
Edit: v_Int is a typedef I declared to be a vector of integers
In first implementation, neighbour is not i, its Adjacency_List[x][i].
int neighbour = Adjacency_List[x][i];
if (visited[neighbour] != 1) { //If neighbour not visited, recursively go there
dfs(neighbour, Adjacency_List, visited);
}

How to do a DFS on a tree? (not necessarily binary)

I have a tree of n nodes (labeled 0 to n). I used two vectors to hold the edge information.
typedef std::vector<std::vector<int>> graph;
The input is n-1 edges in the form:
0 1
1 2
2 3
and so on
I'm told node 0 is always the root node.
I scan the edges using the following:
for (int i = 0; i < n-1; i++) {
scanf("%d %d", &a, &b);
g[a].push_back(b);
g[b].push_back(a); // the second approach doesn't use this line
}
This is my simple dfs:
void dfs(graph &g, int v) {
std::vector<int> visited; // I don't use a visited array for the second approach
for (int i = 0; i < g.size(); i++) {
visited.push_back(0);
}
std::stack<int> s;
std::set<int> t;
s.push(v);
while (!s.empty()) {
int i = s.top(); s.pop();
// do stuff
for (int i = 0; i < g[v].size(); i++) {
if (!visited[i]) {
visited[i] = true;
s.push(g[v][i]);
}
}
}
}
For example say we have 4 nodes and the following edges:
0 1
0 2
3 2
2 4
Say that I'm interested in the sub tree starting at 2. The above approach won't work because I'm inserting undirected edges 0 2 and 2 0. So when I start my dfs at 2 I add node 0 to my stack which is wrong.
I tried another approach of only inserting the edges given only but that also didn't work because in the example I would've inserted 3 2 which is an edge from 3 to node 2 and so when I start my dfs at node 2 I won't be able to reach node 3.
I feel like the problem is simple and I'm missing some big idea!
Since your graph is a rooted tree, you can do the following preprocessing.
Start a DFS from root (vertex #0);
For each vertex u, store its parent v. It means that if you travel alongside shortest path from root to u, the second-to-last vertex on this path will be v. Notice that in any tree there is exactly one shortest path from one vertex to another. Let's say that you have an array parent such that parent[u] = v according to above definition, and parent[0] = -1.
You can compute parent array by noticing, that if you do s.push(g[v][i]), then v is the parent of i (otherwise you would have visited i first);
Since parent[v] is the previous vertex on shortest path from global root (vertex 0), it is also the previous vertex on shortest path from any vertex x, which contains v in its subtree.
Now when you want to DFS over subtree of vertex u, you do DFS as you do it now, but do not visit the parent of any vertex. Say, if you want to do s.push(v), while parent[u] = v, do not do it. This way you will never leave the subtree of u.
Actually, knowing parent, you can get rid of your visited array. When you "do stuff" with vertex v, the only neighbour of v that is already visited is parent[v]. This property does not depend on the initial vertex, whose subtree you want to traverse. The DFS code would look like this (assuming you've done preprocessing to obtain parent:
void dfs(graph &g, vector<int> &parent, int v) {
std::stack<int> s;
s.push(v);
while (!s.empty()) {
int v = s.top(); s.pop(); // By the way, you have mistake here: int i = s.top().
// do stuff
for (int i = 0; i < g[v].size(); i++) {
if (parent[v] != g[v][i]) {
s.push(g[v][i]);
}
}
}
}
PS This approach is somehow similar to your second approach: it only treats edges that go from root to subtree. But it does not have the flaw, such as in your example with "3 2" being the wrong direction, because you infer direction algorithmically by doing DFS from root.

Depth First Search: Formatting output?

If I have the following graph:
Marisa Mariah
\ /
Mary---Maria---Marian---Maryanne
|
Marley--Marla
How should be Depth First Search function be implemented such that I get the output if "Mary" is my start point ?
Mary
Maria
Marisa
Mariah
Marian
Maryanne
Marla
Merley
I do realize that the number of spaces equal to depth of the vertex( name ) but I don't how to code that. Following is my function:
void DFS(Graph g, Vertex origin)
{
stack<Vertex> vertexStack;
vertexStack.push(origin);
Vertex currentVertex;
int currentDepth = 0;
while( ! vertexStack.empty() )
{
currentVertex = vertexStack.top();
vertexStack.pop();
if(currentVertex.visited == false)
{
cout << currentVertex.name << endl;
currentVertex.visited = true;
for(int i = 0; i < currentVertex.adjacencyList.size(); i++)
vertexStack.push(currentVertex.adjacencyList[i]);
}
}
}
Thanks for any help !
Just store the node and its depth your stack:
std::stack<std::pair<Vertex, int>> vertexStack;
vertexStack.push(std::make_pair(origin, 0));
// ...
std::pair<Vertex, int> current = vertexStack.top();
Vertex currentVertex = current.first;
int depth = current.second;
If you want to get fancy, you can extra the two values using std::tie():
Vertex currentVertex;
int depth;
std::tie(currentVertex, depth) = vertexStack.top();
With knowing the depth you'd just indent the output appropriately.
The current size of your stack is, BTW, unnecessarily deep! I think for a complete graph it may contain O(N * N) elements (more precisely, (N-1) * (N-2)). The problem is that you push many nodes which may get visited.
Assuming using an implicit stack (i.e., recursion) is out of question (it won't work for large graphs as you may get a stack overflow), the proper way to implement a depth first search would be:
push the current node and edge on the stack
mark the top node visited and print it, using the stack depth as indentation
if there is no node
if the top nodes contains an unvisited node (increment the edge iterator until such a node is found) go to 1.
otherwise (the edge iterator reached the end) remove the top node and go to 3.
In code this would look something like this:
std::stack<std::pair<Node, int> > stack;
stack.push(std::make_pair(origin, 0));
while (!stack.empty()) {
std::pair<Node, int>& top = stack.top();
for (; top.second < top.first.adjacencyList.size(); ++top.second) {
Node& adjacent = top.first.adjacencyList[top.second];
if (!adjacent.visited) {
adjacent.visted = true;
stack.push(std::make_pair(adjacent, 0));
print(adjacent, stack.size());
break;
}
}
if (stack.top().first.adjacencyList.size() == stack.top().second) {
stack.pop();
}
}
Let Rep(Tree) be the representation of the tree Tree. Then, Rep(Tree) looks like this:
Root
<Rep(Subtree rooted at node 1)>
<Rep(Subtree rooted at node 2)>
.
.
.
So, have your dfs function simply return the representation of the subtree rooted at that node and modify this value accordingly. Alternately, just tell every dfs call to print the representation of the tree rooted at that node but pass it the current depth. Here's an example implementation of the latter approach.
void PrintRep(const Graph& g, Vertex current, int depth)
{
cout << std::string(' ', 2*depth) << current.name << endl;
current.visited = true;
for(int i = 0; i < current.adjacencyList.size(); i++)
if(current.adjacencyList[i].visited == false)
PrintRep(g, current.adjacencyList[i], depth+1);
}
You would call this function with with your origin and depth 0 like this:
PrintRep(g, origin, 0);

Modifying an Implementation of Prim's to record weight of shortest path c++

I'm having some trouble getting this implementation of Prim's to track the total weight of the shortest path it finds. The path seems to be correct but I can't figure out where to sum the weights as they are added to the array that stores the paths (since it was written only to store paths used).
I've tried summing pCrawl->weight as each vertex is added to the MST but that seems to be the sum of all the weights on the graph. Same with the values key[].
My question is what can be summed each time a path is added to the MST to reflect the total weight of the MST when all shortest paths have been added.
Here's the code I'm using: http://pastebin.com/TFLGCE0L
The Adjacency List I made: http://pastebin.com/SvgGjEPj
And the map used to create it: Map
The Prim's function looks like this:
// The main function that constructs Minimum Spanning Tree (MST)
// using Prim's algorithm
void PrimMST(struct Graph* graph)
{
int V = graph->V;// Get the number of vertices in graph
int parent[V]; // Array to store constructed MST
int key[V]; // Key values used to pick minimum weight edge in cut
// minHeap represents set E
struct MinHeap* minHeap = createMinHeap(V);
// Initialize min heap with all vertices. Key value of
// all vertices (except 0th vertex) is initially infinite
for (int v = 1; v < V; ++v)
{
parent[v] = -1;
key[v] = INT_MAX;
minHeap->array[v] = newMinHeapNode(v, key[v]);
minHeap->pos[v] = v;
}
// Make key value of 0th vertex as 0 so that it
// is extracted first
key[0] = 0;
minHeap->array[0] = newMinHeapNode(0, key[0]);
minHeap->pos[0] = 0;
// Initially size of min heap is equal to V
minHeap->size = V;
// In the followin loop, min heap contains all nodes
// not yet added to MST.
while (!isEmpty(minHeap))
{
// Extract the vertex with minimum key value
struct MinHeapNode* minHeapNode = extractMin(minHeap);
int u = minHeapNode->v; // Store the extracted vertex number
// Traverse through all adjacent vertices of u (the extracted
// vertex) and update their key values
struct AdjListNode* pCrawl = graph->array[u].head;
while (pCrawl != NULL)
{
int v = pCrawl->dest;
// If v is not yet included in MST and weight of u-v is
// less than key value of v, then update key value and
// parent of v
if (isInMinHeap(minHeap, v) && pCrawl->weight < key[v])
{
key[v] = pCrawl->weight;
parent[v] = u;
decreaseKey(minHeap, v, key[v]);
}
pCrawl = pCrawl->next;
}
}
The structs used look like this:
// A structure to represent a node in adjacency list
struct AdjListNode
{
int dest;
int weight;
struct AdjListNode* next;
};
// A structure to represent an adjacency liat
struct AdjList
{
struct AdjListNode *head; // pointer to head node of list
};
// A structure to represent a graph. A graph is an array of adjacency lists.
// Size of array will be V (number of vertices in graph)
struct Graph
{
int V;
struct AdjList* array;
};
// Structure to represent a min heap node
struct MinHeapNode
{
int v;
int key;
};
// Structure to represent a min heap
struct MinHeap
{
int size; // Number of heap nodes present currently
int capacity; // Capacity of min heap
int *pos; // This is needed for decreaseKey()
struct MinHeapNode **array;
};
I feel like I'm in way over my head in this data structures course, hence trying to use code from the internet to solve this small part of the assignment without fulling understanding :/
Thanks,
Michael
You are doing the right thing. Sum of minimum weights (from Prim's) can be equal to sum of all the weights on the graph. Consider the case when there are 4 nodes in a graph and node 1 is at the center and is connected to nodes 2, 3 and 4 with weights of w. 2, 3 and 4 are not connected among themselves. In this case Prim's weight would come out to be 3*w which is same as total weight. I would suggest you to use few different cases, that would clarify what I'm saying.
Edit:
Here is the issue, you are not updating the sum properly.
This -
weightTotal += pCrawl->weight
should be -
weightTotal += pCrawl->weight - key[v]

C++ Implementation of Graph Algorithm

I am trying to implement the Breadth-first search algorithm, in order to find the shortest distance between two vertices. I have developed a Queue object to hold and retrieve objects, and I have a two-dimensional array to hold the length of the edges between two given vertices. I am attempting to fill a two-dimensional array to hold the shortest distance between two vertices.
The problem I am having, however, is that no matter what two vertices I request the shortest distance of, 0 is returned. Here is my implementation of the algorithm; if you can set me on the right track and help me figure out my problem, that would be fantastic.
for (int i = 0; i < number_of_vertex; i++)
//For every vertex, so that we may fill the array
{
int[] dist = new int[number_of_vertex];
//Initialize a new array to hold the values for the distances
for (int j = 0; x < number_of_vertex; j++)
{
dist[j] = -1;
//All distance values will be set to -1 by default; this will be changed later on
}
dist[i] = 0; //The source node's distance is set to 0 (Pseudocode line 4)
myQueue.add(i); //Add the source node's number to the queue (Pseudocode line 3)
while (!myQueue.empty()) //Pseudocode line 5
{
int u = myQueue.eject(); //Pseudocode line 6
for (int y = 0; y < number_of_vertex; y++) //Pseudocode line 7
{
if (edge_distance(u,y) > 0)
{
if (dist[y] == -1)
{
myQueue.add(y);
dist[y] = dist[u] + 1;
shortest_distance[i][u] = dist[y];
}
}
}
}
}
Ok... i guess the problem is about the used algorithm and about used terms.
"In order to find the shortest distance between two vertices" you mean the shortest path between two vertices in a connected graph?
The algorithm you are trying to write is the Dijkstra's algorithm (this is the name).
http://www.cs.berkeley.edu/~vazirani/algorithms/chap4.pdf