I've got this code to find a minimum spanning tree for given graph. I need to revert this algorithm to get an hamiltonian cycle instead of hamiltonian path. Can u help me to revert this code to get an hamiltonian cycle? I need it to Travelling Salesman Problem. I tried to remove and change this fragment of code responsible to discarding next_edge if edge causes cycle and add additional edge from vertices 1-2, but when i removed it, a program returns arrayIndexOutOfBoundsException, and when I changed if(x != y) to if(x==y) or delete this conditional, output graph were refilled by 0.
I'm very beginner in programming and I can't resolve this problem by myself.
It is the code:
import java.util.*;
import java.lang.*;
import java.io.*;
class Graph {
// A class to represent a graph edge
class Edge implements Comparable<Edge> {
int src, dest, weight;
// Comparator function used for sorting edges
// based on their weight
public int compareTo(Edge compareEdge) {
return this.weight - compareEdge.weight;
}
};
// A class to represent a subset for union-find
class subset {
int parent, rank;
};
int V, E; // V-> no. of vertices & E->no.of edges
Edge edge[]; // collection of all edges
// Creates a graph with V vertices and E edges
Graph(int v, int e) {
V = v;
E = e;
edge = new Edge[E];
for (int i = 0; i < e; ++i) {
edge[i] = new Edge();
}
}
// A utility function to find set of an element i
// (uses path compression technique)
int find(subset subsets[], int i) {
// find root and make root as parent of i (path compression)
if (subsets[i].parent != i) {
subsets[i].parent = find(subsets, subsets[i].parent);
}
return subsets[i].parent;
}
// A function that does union of two sets of x and y
// (uses union by rank)
void Union(subset subsets[], int x, int y) {
int xroot = find(subsets, x);
int yroot = find(subsets, y);
// Attach smaller rank tree under root of high rank tree
// (Union by Rank)
if (subsets[xroot].rank < subsets[yroot].rank) {
subsets[xroot].parent = yroot;
} else if (subsets[xroot].rank > subsets[yroot].rank) {
subsets[yroot].parent = xroot;
}
// If ranks are same, then make one as root and increment
// its rank by one
else {
subsets[yroot].parent = xroot;
subsets[xroot].rank++;
}
}
// The main function to construct MST using Kruskal's algorithm
void KruskalMST() {
Edge result[] = new Edge[V]; // Tnis will store the resultant MST
int e = 0; // An index variable, used for result[]
int i = 0; // An index variable, used for sorted edges
for (i = 0; i < V; ++i) {
result[i] = new Edge();
}
// Step 1: Sort all the edges in non-decreasing order of their
// weight. If we are not allowed to change the given graph, we
// can create a copy of array of edges
Arrays.sort(edge);
// Allocate memory for creating V ssubsets
subset subsets[] = new subset[V];
for (i = 0; i < V; ++i) {
subsets[i] = new subset();
}
// Create V subsets with single elements
for (int v = 0; v < V; ++v) {
subsets[v].parent = v;
subsets[v].rank = 0;
}
i = 0; // Index used to pick next edge
// Number of edges to be taken is equal to V-1
while (e < V - 1) {
// Step 2: Pick the smallest edge. And increment
// the index for next iteration
Edge next_edge = new Edge();
next_edge = edge[i++];
int x = find(subsets, next_edge.src);
int y = find(subsets, next_edge.dest);
// If including this edge does't cause cycle,
// include it in result and increment the index
// of result for next edge
if (x != y) {
result[e++] = next_edge;
Union(subsets, x, y);
}
// Else discard the next_edge
}
// print the contents of result[] to display
// the built MST
System.out.println("Following are the edges in " +
"the constructed MST");
for (i = 0; i < e; ++i)
System.out.println(result[i].src + " -- " +
result[i].dest + " == " + result[i].weight);
}
// Driver Program
public static void main (String[] args) {
/* Let us create following weighted graph
10
0--------1
| \ |
6| 5\ |15
| \ |
2--------3
4 */
int V = 4; // Number of vertices in graph
int E = 5; // Number of edges in graph
Graph graph = new Graph(V, E);
// add edge 0-1
graph.edge[0].src = 0;
graph.edge[0].dest = 1;
graph.edge[0].weight = 10;
// add edge 0-2
graph.edge[1].src = 0;
graph.edge[1].dest = 2;
graph.edge[1].weight = 6;
// add edge 0-3
graph.edge[2].src = 0;
graph.edge[2].dest = 3;
graph.edge[2].weight = 5;
// add edge 1-3
graph.edge[3].src = 1;
graph.edge[3].dest = 3;
graph.edge[3].weight = 15;
// add edge 2-3
graph.edge[4].src = 2;
graph.edge[4].dest = 3;
graph.edge[4].weight = 4;
graph.KruskalMST();
}
}
Related
public class Problem3 {
public static void main (String [] args){
Scanner sc= new Scanner (System.in);
System.out.println("Enter no. of Islands");
int n= sc.nextInt();
Graph g = new Graph (n);
System.out.println("Enter no. of one-way bridges");
int m= sc.nextInt();
System.out.println("Enter no. of island you want to be intially on");
int r= sc.nextInt();
try{ for (int i=0; i<m;i++){
System.out.println("This one-way bridge connects between");
int u = sc.nextInt();
int v = sc.nextInt();
if(u == v || u>n || v>n){ throw new Bounds("");}
else{ g.addEgde(u-1, v-1);}
}
g.topoSort();}
catch(IndexOutOfBoundsException e){
System.out.println("Please enter a valid input!");
}
catch(Bounds e){
System.out.println("Please enter a valid input!");
}
}
public static class Bounds extends Exception{
public Bounds (String message){
super(message);
}}
static class Graph {
int V;
LinkedList<Integer>[] adjList;
Graph(int V) {
this.V = V;
adjList = new LinkedList[V];
for (int i = 0; i < V; i++) {
adjList[i] = new LinkedList<>();
}
}
public void addEgde(int u, int v) {
adjList[u].addFirst(v);
}
public void topoSort() {
boolean[] visited = new boolean[V];
stack stack = new stack();
for (int i = 0; i < V; i++) {
if (!visited[i]) {
topoSortRE(i, visited, stack);
}
}
System.out.println("Topological Sort: ");
int size = stack.size();
for (int i = 0; i <size ; i++) {
System.out.print(stack.pop()+ 1 + " ");
}
}
public void topoSortRE(int s, boolean[] visited, stack stack) {
visited[s] = true;
for (int i = 0; i < adjList[s].size(); i++) {
int vertex = adjList[s].get(i);
if (!visited[vertex])
topoSortRE(vertex, visited, stack);
}
stack.push(s);
}}}
The following code is an attempt to solve the following problem:
There are many islands that are connected by one-way bridges, that is, if a bridge connects
islands a and b, then you can only use the bridge to go from a to b but you cannot travel back
by using the same. If you are on island a, then you select (uniformly and randomly) one of
the islands that are directly reachable from a through the one-way bridge and move to that
island. You are stuck on an island if you cannot move any further. It is guaranteed that if
there is a directed path from one island to the second there is no path that leads from the
second back to the first. In other words the formed graph is a Directed Acyclic Graph.
Find the island that you are most likely to get stuck on; that is the island that you can
possibly reach with the maximum number of paths from all other islands.
Input format:
First line: Three integers n (the number of islands), m (the number of one-way bridges), and r
(the index of the island you are initially on)
Next m lines: Two integers ui and vi representing a one-way bridge from island ui to vi.
Output format:
Print the index of the island that you are most likely to get stuck on. If there are multiple
islands, then print them in the increasing order of indices (space separated values in a single
line).
Sample input
5, 7, 1
(1, 2)
(1, 3)
(1, 4)
(1, 5)
(2, 4)
(2, 5)
(3, 4)
Sample output
4
I wrote the code to topologically sort the graph but I am having issues with how to make the input r the intial island and also how to make the output be the most probable island to be stuck on. I know that the island I'm most likely to be stuck on is the island that has the most indegrees and no outdegrees but don't know how to implement that.
For each node make a value (real number) representing probability that you will reach it from your starting island. At first, set this value for initial node to 1 and 0 for other nodes.
During the topological sort, when you're in node v, add its probability value divided by number of neighbors to each neighbor's value (in other words, since you know that the probability of getting to v is v.value, then the probability of reaching its neighbor should be increased by v.value * ppb of choosing this neighbor, that is 1 / #_of_neighbors). In this way, whenever you're in some node during topological sort, its value will be equal to the total probability of reaching it.
Your answer is an ending island (node with outdegree 0) with largest value.
Your topological sort seems wrong, you're doing something that looks like DFS. In topological sort you want to visit each vertex after visiting all vertices with an edge ending in it.
About implementation, I changed your DFS into topological sort and added those probabilities I've talked about. I left the part about choosing best ending vertex to you, I don't think doing all the work for someone is educational in any way. Also, I do not guarantee that my changes below do not contain any spelling mistakes, etc. I did my best, but I have not run this code.
static class Graph {
int V;
LinkedList<Integer>[] adjList;
Graph(int V) {
this.V = V;
adjList = new LinkedList[V];
probability = new double[V];
for (int i = 0; i < V; i++) {
adjList[i] = new LinkedList<>();
}
}
public void addEgde(int u, int v) {
adjList[u].addFirst(v);
}
public void topoSort(int start) {
double[] probability;
probability[start] = 1;
int[] indegree = new int[V];
stack stack = new stack();
for (int i = 0; i < V; i++) {
probability[i] = 0;
for (int j = 0; j < adjList[i].size(); ++j) {
indegree[adjList[i][j]] += 1;
}
}
probability[start] = 1;
for(int i = 0; i < V; ++i)
{
if(indegree[i] == 0)
stack.push(i);
}
while(stack.size())
{
int v = stack.pop();
for (int i = 0; i < adjList[v].size(); ++i)
{
indegree[adjList[v][i]] -= 1;
probability[adjList[v][i]] += probability[v] / (double)(adjList[v].size());
if(indegree[adjList[v][i]] == 0)
stack.push(adjList[v][i]);
}
}
//probability array now contains all probabilities to visit each node
}
}
}
I'm so stuck, I would greatly appreciate some help. I'm currently learning Algorithms, but I have no idea where to start.
I was given code recently (We have only really done theory so seeing the code has scared me to my core) And I have been given the task to modify this code to take details from a text file and put it in a graph. The text file is similar to this.
Trout is-a fish
Fish has gills
Fish has fins
Fish is food
Fish is-an animal
Just a lot more in there. I am just wondering. How I would get started with this whole thing? There are a million questions I have to ask, but I feel like I could figure those out if only I knew how to assign the Vertices using the text file? The code I was supplied and have to edit is below. Any help would be great, Just a push in the right direction if you will.
(Also, What the heck is weight, in the addEdge class? I know it's the "cost" of traversing the edge, but how do I assign the weight?)
Thanks!
public class Graph {
private final int MAX_VERTS = 20;
private final int INFINITY = 1000000;
private Vertex vertexList[]; // list of vertices
private int adjMat[][]; // adjacency matrix
private int nVerts; // current number of vertices
private int nTree; // number of verts in tree
private DistPar sPath[]; // array for shortest-path data
private int currentVert; // current vertex
private int startToCurrent; // distance to currentVert
// -------------------------------------------------------------
public Graph() // constructor
{
vertexList = new Vertex[MAX_VERTS];
// adjacency matrix
adjMat = new int[MAX_VERTS][MAX_VERTS];
nVerts = 0;
nTree = 0;
for(int j=0; j<MAX_VERTS; j++) // set adjacency
for(int k=0; k<MAX_VERTS; k++) // matrix
adjMat[j][k] = INFINITY; // to infinity
sPath = new DistPar[MAX_VERTS]; // shortest paths
} // end constructor
// -------------------------------------------------------------
public void addVertex(char lab)
{
vertexList[nVerts++] = new Vertex(lab);
}
// -------------------------------------------------------------
public void addEdge(int start, int end, int weight)
{
adjMat[start][end] = weight; // (directed)
}
// -------------------------------------------------------------
public void path() // find all shortest paths
{
int startTree = 0; // start at vertex 0
vertexList[startTree].isInTree = true;
nTree = 1; // put it in tree
// transfer row of distances from adjMat to sPath
for(int j=0; j<nVerts; j++)
{
int tempDist = adjMat[startTree][j];
sPath[j] = new DistPar(startTree, tempDist);
}
// until all vertices are in the tree
while(nTree < nVerts)
{
int indexMin = getMin(); // get minimum from sPath
int minDist = sPath[indexMin].distance;
if(minDist == INFINITY) // if all infinite
{ // or in tree,
System.out.println("There are unreachable vertices");
break; // sPath is complete
}
else
{ // reset currentVert
currentVert = indexMin; // to closest vert
startToCurrent = sPath[indexMin].distance;
// minimum distance from startTree is
// to currentVert, and is startToCurrent
}
// put current vertex in tree
vertexList[currentVert].isInTree = true;
nTree++;
adjust_sPath(); // update sPath[] array
} // end while(nTree<nVerts)
displayPaths(); // display sPath[] contents
nTree = 0; // clear tree
for(int j=0; j<nVerts; j++)
vertexList[j].isInTree = false;
} // end path()
// -------------------------------------------------------------
public int getMin() // get entry from sPath
{ // with minimum distance
int minDist = INFINITY; // assume minimum
int indexMin = 0;
for(int j=1; j<nVerts; j++) // for each vertex,
{ // if it’s in tree and
if( !vertexList[j].isInTree && // smaller than old one
sPath[j].distance < minDist )
{
minDist = sPath[j].distance;
indexMin = j; // update minimum
}
} // end for
return indexMin; // return index of minimum
} // end getMin()
// -------------------------------------------------------------
public void adjust_sPath()
{
// adjust values in shortest-path array sPath
int column = 1; // skip starting vertex
while(column < nVerts) // go across columns
{
// if this column’s vertex already in tree, skip it
if( vertexList[column].isInTree )
{
column++;
continue;
}
// calculate distance for one sPath entry
// get edge from currentVert to column
int currentToFringe = adjMat[currentVert][column];
// add distance from start
int startToFringe = startToCurrent + currentToFringe;
// get distance of current sPath entry
int sPathDist = sPath[column].distance;
// compare distance from start with sPath entry
if(startToFringe < sPathDist) // if shorter,
{ // update sPath
sPath[column].parentVert = currentVert;
sPath[column].distance = startToFringe;
}
column++;
} // end while(column < nVerts)
} // end adjust_sPath()
// -------------------------------------------------------------
public void displayPaths()
{
for(int j=0; j<nVerts; j++) // display contents of sPath[]
{
System.out.print(vertexList[j].label + "="); // B=
if(sPath[j].distance == INFINITY)
System.out.print("inf"); // inf
else
System.out.print(sPath[j].distance); // 50
char parent = vertexList[ sPath[j].parentVert ].label;
System.out.print("(" + parent + ") "); // (A)
}
System.out.println("");
}
// -------------------------------------------------------------
} // end class Graph
The way I do graphs is that I have a list or array of edges instead of storing that information in a matrix. I would create an inner edge class which contains two nodes, since this is a directional graph the two nodes have to be distinct from each other. You can also use the edge class instead of the DistPar class to track the shortest path. (Or you can repurpose the distPar class to fulfill the edge functionality for you).
Weights are properties given to edges. The analogy I like to use is airline routes. Imagine that there was a single airline route from New York to LA but it cost $300 to get a ticket on that plane, but, if you took a route through a connecting airport, the ticket only costs $150. In this situation, you can think of each airport as a node and the routes between the airports are the edges which connect the nodes together. The 'weight' of the nodes in this case is the price. If you're looking to get from New York to LA, at the cheapest cost possible, you would take the cheaper route even though it passes through more airports.
Weights basically shift the definition of the shortest path between any two nodes from the least amount of connecting nodes to the least weight between these two nodes. Dijkstra's Algorithm is similar to the one which you have implemented, but also takes advantage of weights, redefining the shortest path as we have above.
I hope this was helpful!
I have an assignment where I have to compute the Chromatic Polynomials of a graph. According to the “Fundamental Reduction Theorem”:
A recursive way of computing the chromatic polynomial is based on edge contraction: for a pair of adjacent vertices u and v the graph Guv is obtained by merging the two vertices and removing the edge between them. Then the chromatic polynomial satisfies the recurrence relation:
P(G, x) = P(G − uv, x) − P(Guv, x)
where u and v are adjacent vertices and G − uv is the graph with the edge uv removed.
Likewise, Chromatic Polynomials can be found when by:
A recursive way of computing the chromatic polynomial is based on edge contraction: for a pair of non-adjacent vertices u and v the graph Guv is obtained by merging the two vertices and adding the edge between them. Then the chromatic polynomial satisfies the recurrence relation
P(G, x) = P(G + uv, x) + P(Guv, x)
where u and v are adjacent vertices and G + uv is the graph with the edge uv added.
It was determined for this assignment that when we want to make null graphs based on the previous formula was when the edges of the graph is <= (the number of vertices) * ((number of vertices-1)/4). This is the “break point” for determining if it is more efficient to go toward null graphs or complete graphs.
Additionally, I have a class for creating Polynomials. So I don’t have to post two classes I’ll the Polynomial class here summarize here:
Constructors:
Polynomial() – creates a constant polynomial P(x) = 1.
Polynomial(int a)- creates a linear polynomial of the form P(x) = x + a.
Polynomial(int a, int b) – creates a polynomial of the form a * x^b.
int degree() – returns the degree of the polynomial.
Polynomial plus(Polynomial b) – returns the sum of this polynomial and b, i.e, c = this + b
Polynomial minus(Polynomial b) – returns the difference of this polynomial and , i.e, c = this–b
Polynomial times(Polynomial b) – returns the product of this polynomial and b, return (this*b)
Polynomial compose(Polynomial b)- returns the composite of this polynomial and b. return this(b(x)) – compute using Horner’s method.
boolean equals(Polynomial b)- returns true whenever this polynomial and b are identical.
int evaluate(int x)- evaluate this polynomial at x. return this(x).
Polynomial differentiate()- return the derivative of the polynomial.
String toString()- return the textual representation of this polynomial.
The following is the Graph class. It uses a Bag data structure array that is implemented using a linked list. So for example, all vertices that are adjacent to vertex 0 will be in the Bag located at Bag[0]. I need help doing the recursive part where it computes a Chromatic Polynomial. I have some comments of questions I have in the chromaticPolynomial method as well as mergeVertices method. I am not sure if what I am thinking in these two methods is correct and would appreciate anyone’s help on it. Thanks in advance.
import java.util.Arrays;
public class Graph {
private final int V;
private int E;
private Bag<Integer>[] adj;
/**
* Create an empty graph with V vertices.
*/
public Graph(int V) {
if (V < 0) throw new RuntimeException("Number of vertices must be nonnegative");
this.V = V;
this.E = 0;
adj = (Bag<Integer>[]) new Bag[V];
for (int v = 0; v < V; v++) {
adj[v] = new Bag<Integer>();
}
}
/**
* Create a random graph with V vertices and E edges.
* Expected running time is proportional to V + E.
*/
public Graph(int V, int E) {
this(V);
if (E < 0) throw new RuntimeException("Number of edges must be nonnegative");
for (int i = 0; i < E; i++) {
int v = (int) (Math.random() * V);
int w = (int) (Math.random() * V);
addEdge(v, w);
}
}
/**
* Create a digraph from input stream.
*/
public Graph(In in) {
this(in.readInt());
int E = in.readInt();
for (int i = 0; i < E; i++) {
int v = in.readInt();
int w = in.readInt();
addEdge(v, w);
}
}
/**
* Copy constructor.
*/
public Graph(Graph G) {
this(G.V());
this.E = G.E();
for (int v = 0; v < G.V(); v++) {
// reverse so that adjacency list is in same order as original
Stack<Integer> reverse = new Stack<Integer>();
for (int w : G.adj[v]) {
reverse.push(w);
}
for (int w : reverse) {
adj[v].add(w);
}
}
}
/**
* Return the number of vertices in the graph.
*/
public int V() { return V; }
/**
* Return the number of edges in the graph.
*/
public int E() { return E; }
/**
* Add the edge v-w to graph.
*/
public void addEdge(int v, int w) {
E++;
adj[v].add(w);
adj[w].add(v);
}
/**
* Remove edge from v-w to graph.
*/
public void removeEdge(int v, int w){
E--;
adj[v].remove(w);
adj[w].remove(v);
}
public Polynomial chromaticPolynomial(Graph G){
// null graph is reached, return a polynomial that is G1.minus(G2)
if(G.V() == 0) return new Polynomial(); // how do I create a Chromatic Polynomial when this condition is reached?
// complete graph is reached, return a polynomial that is G1.plus(G2). If the number of vertices in a complete graph is n, then the number of edges is equal to n(n-1)/2.
if(G.E() == ((G.V() - (G.V() - 1))/2)) return new Polynomial(); // how do I create a Chromatic Polynomial when this condtion is reached?
// head toward a null graph.
if(G.E() <= G.V()*(G.V()-1/4)){
/**
for every vertex (u) and every edge (v) from that vertex, create a graph that has an edge removed (G1)
and a graph with merged vertices (G2), then recurse until a null graph is reached.
*/
for(int u = 0; u < G.V(); u++){
for(int v : adj[u]){
Graph G1 = new Graph(G);
Graph G2 = new Graph(G);
G1.removeEdge(u,v);
G2.mergeVertices(u,v);
chromaticPolynomial(G1);
chromaticPolynomial(G2);
// reutrn a polynomial here?
}
}
}
// head towards a complete graph.
else{
/**
for every vertex (u) and every edge (v) from that vertex, create a graph that has an edge added (G1) and
a graph with merged verticies (G2), then recures unitl all these graphs are a complete graph.
*/
for(int u = 0; u < G.V(); u++){
for(int v : adj[u]){
Graph G1 = new Graph(G);
Graph G2 = new Graph(G);
G1.addEdge(u,v);
G2.mergeVertices(u,v);
chromaticPolynomial(G1);
chromaticPolynomial(G2);
// return a polynomial here?
}
}
}
// return nothing. It didn't work.
return null;
}
public void mergeVertices(int vert1, int vert2){
// edge has already been removed between these two.
// just have to renumber the vertices so one is "removed"
/**
does this look correct?
*/
for(int u = 0; u < this.V(); u++){
for(int w: adj[u]){
if(w > vert1 || w > vert2) w--;
if(u > vert1 || u > vert2) u--;
}
}
}
/**
* Return the list of neighbors of vertex v as in Iterable.
*/
public Iterable<Integer> adj(int v) {
return adj[v];
}
/**
* Return a string representation of the graph.
*/
public String toString() {
StringBuilder s = new StringBuilder();
String NEWLINE = System.getProperty("line.separator");
s.append(V + " vertices, " + E + " edges " + NEWLINE);
for (int v = 0; v < V; v++) {
s.append(v + ": ");
for (int w : adj[v]) {
s.append(w + " ");
}
s.append(NEWLINE);
}
return s.toString();
}
Background
I am trying to code Dijkstra's algorithm in O(mlogn) time, where m is the number of edges and n is the number of nodes. I am using to find the shortest path between a given starting node and a given ending node. And I'm pretty new at this.
Here is the algorithm I have come up with:
Assume the graph is represented by an adjacency matrix and each node has a row index.
Initialize starting node distance to zero, and all other nodes to inifinity, in the heap.
Create a list of shortest paths, equal to the number of nodes in the graph, set to 0.
While the index of the node that corresponds to the minimum element in the heap
has no value in the list of shortest paths and heap has node distances, do:
Remove the minimum node distance from the heap, and bubble as necessary to fill the removed node.
Put the minimum node distance into the list of shortest paths at its row index.
For all nodes that were adjacent to the node with the minimum distance (that was just removed), do:
Update the distances in the heap for the current node, using the following calculation:
min((deleted node distance + adjacent edge weight), current node's distance)
Reorganize the heap to be a minimum heap.
Return value in the list of shortest paths at the location of the end node.
This is O(mlogn) because you only update the distances once per edge.
"It takes linear time
to initialize the heap, and then we perform m updates at a cost of O(log n) each for a total time of O(mlog n)." - http://www.cs.cmu.edu/~avrim/451f07/lectures/lect1011.pdf
Problem
In order to update the distances from the starting vertex in the correct location in the heap, insertions to the heap must be key-value pairs - with the key being the node (row index) and the value being the distance.
There are lecture slides online that say each entry in a priority queue ADT is a key-value pair (otherwise, how could it prioritize?).
Question
The methods for PriorityQueue have at most one parameter, so how do you insert a key associated with a value?
This must be done in a single file with a specific name (i.e. It is my understanding that I can't make a KeyValuePair class implementing Comparator).
I'd love to hear your thoughts.
To use JDK's implementation of priority queue for your application, you can maintain a Map<Key, Value> in addition to PriorityQueue<Value>. In your case, Key represents a node and Value is an object that holds the shortest distance to a node. To update the distance to a node, you first look up its corresponding distance object in the map. Then, you remove the distance object from the priority queue. Next, you update the distance object. Finally, you insert the distance object back in the priority queue.
Below is the Dijkstra implementation using priority_queue .
Here ignore the InputReader class as it is for fast input . We can maintain priority according to "Value" of pair in key value pair . Then choose the Pair with minimum cost i.e value .
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.InputMismatchException;
import java.util.List;
import java.util.PriorityQueue;
/**
* By: Rajan Parmar
* At : HackerRank
**/
public class Dijkstra {
// node ,pair ( neighbor , cost)
static HashMap < Integer , HashSet <Pair>> node;
static PrintWriter w;
public static void main(String [] s) throws Exception{
InputReader in;
boolean online = false;
String fileName = "input";
node = new HashMap<Integer, HashSet<Pair>>();
//ignore online if false it is for online competition
if (online) {
//ignore
in = new InputReader(new FileInputStream(
new File(fileName + ".txt")));
w = new PrintWriter(new FileWriter(fileName + "Output.txt"));
} else {
// for fast input output . You can use any input method
in = new InputReader(System.in);
w = new PrintWriter(System.out);
}
// Actual code starts here
int t;
int n, m;
t = in.nextInt();
while(t-- > 0){
n = in.nextInt();
m = in.nextInt();
while(m-- > 0){
int x,y,cost;
x = in.nextInt();
y = in.nextInt();
cost = in.nextInt();
if(node.get(x)==null){
node.put(x, new HashSet());
node.get(x).add(new Pair(y,cost));
}
else{
node.get(x).add(new Pair(y,cost));
}
if(node.get(y)==null){
node.put(y, new HashSet());
node.get(y).add(new Pair(x,cost));
}
else{
node.get(y).add(new Pair(x,cost));
}
}
int source = in.nextInt();
Dijkstra(source,n);
node.clear();
System.out.println("");
}
}
static void Dijkstra(int start , int n) {
int dist[] = new int[3001];
int visited[] = new int[3001];
Arrays.fill(dist, Integer.MAX_VALUE);
Arrays.fill(visited, 0);
dist[start] = 0 ;
PriorityQueue < Pair > pq = new PriorityQueue();
//this will be prioritized according to VALUES (i.e cost in class Pair)
pq.add(new Pair(start , 0));
while(!pq.isEmpty()){
Pair pr = pq.remove();
visited[pr.neighbor] = 1;
for(Pair p:node.get(pr.neighbor)){
if(dist[p.neighbor] > dist[pr.neighbor] + p.cost){
dist[p.neighbor] = dist[pr.neighbor] + p.cost;
//add updates cost to vertex through start vertex
if(visited[p.neighbor]==0)
pq.add(new Pair(p.neighbor ,dist[p.neighbor] ));
}
}
}
for(int i=1;i<=n;i++){
if(i==start) continue;
if(visited[i]==0)
dist[i]=-1;
System.out.print(dist[i]+" ");
}
}
static class Pair implements Comparable {
int neighbor;
int cost;
public Pair(int y, int cost) {
// TODO Auto-generated constructor stub
neighbor = y;
this.cost = cost;
}
#Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
Pair pr = (Pair)o;
if(cost > pr.cost)
return 1;
else
return -1;
}
}
//Ignore this class , it is for fast input.
static class InputReader {
private InputStream stream;
private byte[] buf = new byte[8192];
private int curChar, snumChars;
private SpaceCharFilter filter;
public InputReader(InputStream stream) {
this.stream = stream;
}
public int snext() {
if (snumChars == -1)
throw new InputMismatchException();
if (curChar >= snumChars) {
curChar = 0;
try {
snumChars = stream.read(buf);
} catch (IOException e) {
throw new InputMismatchException();
}
if (snumChars <= 0)
return -1;
}
return buf[curChar++];
}
public int nextInt() {
int c = snext();
while (isSpaceChar(c))
c = snext();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = snext();
}
int res = 0;
do {
if (c < '0' || c > '9')
throw new InputMismatchException();
res *= 10;
res += c - '0';
c = snext();
} while (!isSpaceChar(c));
return res * sgn;
}
public long nextLong() {
int c = snext();
while (isSpaceChar(c))
c = snext();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = snext();
}
long res = 0;
do {
if (c < '0' || c > '9')
throw new InputMismatchException();
res *= 10;
res += c - '0';
c = snext();
} while (!isSpaceChar(c));
return res * sgn;
}
public int[] nextIntArray(int n) {
int a[] = new int[n];
for (int i = 0; i < n; i++)
a[i] = nextInt();
return a;
}
public String readString() {
int c = snext();
while (isSpaceChar(c))
c = snext();
StringBuilder res = new StringBuilder();
do {
res.appendCodePoint(c);
c = snext();
} while (!isSpaceChar(c));
return res.toString();
}
public boolean isSpaceChar(int c) {
if (filter != null)
return filter.isSpaceChar(c);
return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
}
public interface SpaceCharFilter {
public boolean isSpaceChar(int ch);
}
}
}
This will take input in following format .
First line be T (no. of test case).
For each test case next line input will be N and M , where N is no of nodes , M is no of edges.
Next M line contains 3 integers i.e x,y,W. It represents edge between node x and y with weight W.
Next line contain single integer i.e. Source node .
Output :
Print shortest distance to all node from given source node . If node is unreachable print -1.
e.g
Input :
1
6 8
1 2 1
1 5 4
2 5 2
2 3 2
5 6 5
3 6 2
3 4 1
6 4 3
1
Output : (shortest distance of all node from node 1)
1 3 4 3 5
I appreciate the answers to my question and at the time I chose the Map answer because given my limited understanding of the language, it seemed easier for me to implement.
It turns out that I overlooked an important detail that made the problem much simpler than I thought it was: if I maintain an array of distances and insert the nodes into the heap (instead of the distances), to use as references to the distance array, I was able to sort the nodes based on their values.
In this implementation, I didn't need to contrive a key-value property after all. After updating the values in the distance array, I had to remove and re-add those specific nodes to the heap in order for the heap to stay current and sorted, as suggested by #reprogrammer.
Once I changed what I was putting into the heap, the algorithm was very similar to the one found on Wikipedia.
Here is the code I ended up using, in case anyone has the same problem. Note: the magic part is the creation of the PriorityQueue (which is similar to what was suggested by #stevevls):
import java.util.*;
import java.io.File; //Because files were used to test correctness.
import java.lang.Math;
public class Dijkstra{
//This value represents infinity.
public static final int MAX_VAL = (int) Math.pow(2,30);
/* Assumptions:
If G[i][j] == 0, there is no edge between vertex i and vertex j
If G[i][j] > 1, there is an edge between i and j and the value of G[i][j] is its weight.
No entry of G will be negative.
*/
static int dijkstra(int[][] G, int i, int j){
//Get the number of vertices in G
int n = G.length;
// The 'i' parameter indicates the starting node and the 'j' parameter
// is the ending node.
//Create a list of size n of shortest paths, initialize each entry to infinity
final int[] shortestPaths = new int[n];
for(int k = 0; k < n; k++){
shortestPaths[k] = MAX_VAL;
}
//Initialize starting node distance to zero.
shortestPaths[i] = 0;
//Make a Priority Queue (a heap)
PriorityQueue<Integer> PQ = new PriorityQueue<Integer>(n,
new Comparator<Integer>()
{
public int compare(Integer p, Integer q)
{
return shortestPaths[p] - shortestPaths[q];
}
} );
//Populate the heap with the nodes of the graph
for(int k = 0; k < n; k++){
PQ.offer(k);
}
//While the heap has elements.
while(PQ.size() > 0){
// Remove the minimum node distance from the heap.
int minimum = PQ.poll();
// Check if graph is disconnected, if so, return -1.
if(shortestPaths[minimum] == MAX_VAL)
{
return -1;
}
// End node has been reached (i.e. you've found the shortest path), return the distance.
if( minimum == j){
return shortestPaths[j];
}
// Take the current node and look through the row to see the vertices adjacent to it (neighbours)
for(int columnIt = 0; columnIt < n; columnIt ++){
// Update the distances in the heap for the current node, using the following calculation:
// min((deleted node distance + adjacent edge weight), current node's distance)
if(G[minimum][columnIt] > 0){
int sum = shortestPaths[minimum] + G[minimum][columnIt];
shortestPaths[columnIt]= Math.min(sum, shortestPaths[columnIt]);
if(shortestPaths[columnIt]==sum)
{
PQ.remove(columnIt);
PQ.offer(columnIt);
}
}
}
}
return -1;
}
Thank you for your answers and advice.
I am resolving the same issue. I know where you can find the answer on you question.
It's a great book with example of code - Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
Site book and Example of code (including an implementation of Dijkstra's algorithm using a PriorityQueue)
This implementation of Dijkstra's algorithm doesn't use Java's standard PriorityQueue implementation. Instead it implements IndexMinPQ, which was discussed earlier in the book with a detailed explanation!
I'm trying to write a program that'll find the MST of a given undirected weighted graph with Kruskal's and Prim's algorithms. I've successfully implemented Kruskal's algorithm in the program, but I'm having trouble with Prim's. To be more precise, I can't figure out how to actually build the Prim function so that it'll iterate through all the vertices in the graph. I'm getting some IndexOutOfBoundsException errors during program execution. I'm not sure how much information is needed for others to get the idea of what I have done so far, but hopefully there won't be too much useless information.
This is what I have so far:
I have a Graph, Edge and a Vertex class.
Vertex class mostly just an information storage that contains the name (number) of the vertex.
Edge class can create a new Edge that has gets parameters (Vertex start, Vertex end, int edgeWeight). The class has methods to return the usual info like start vertex, end vertex and the weight.
Graph class reads data from a text file and adds new Edges to an ArrayList. The text file also tells us how many vertecis the graph has, and that gets stored too.
In the Graph class, I have a Prim() -method that's supposed to calculate the MST:
public ArrayList<Edge> Prim(Graph G) {
ArrayList<Edge> edges = G.graph; // Copies the ArrayList with all edges in it.
ArrayList<Edge> MST = new ArrayList<Edge>();
Random rnd = new Random();
Vertex startingVertex = edges.get(rnd.nextInt(G.returnVertexCount())).returnStartingVertex(); // This is just to randomize the starting vertex.
// This is supposed to be the main loop to find the MST, but this is probably horribly wrong..
while (MST.size() < returnVertexCount()) {
Edge e = findClosestNeighbour(startingVertex);
MST.add(e);
visited.add(e.returnStartingVertex());
visited.add(e.returnEndingVertex());
edges.remove(e);
}
return MST;
}
The method findClosesNeighbour() looks like this:
public Edge findClosestNeighbour(Vertex v) {
ArrayList<Edge> neighbours = new ArrayList<Edge>();
ArrayList<Edge> edges = graph;
for (int i = 0; i < edges.size() -1; ++i) {
if (edges.get(i).endPoint() == s.returnVertexID() && !visited(edges.get(i).returnEndingVertex())) {
neighbours.add(edges.get(i));
}
}
return neighbours.get(0); // This is the minimum weight edge in the list.
}
ArrayList<Vertex> visited and ArrayList<Edges> graph get constructed when creating a new graph.
Visited() -method is simply a boolean check to see if ArrayList visited contains the Vertex we're thinking about moving to. I tested the findClosestNeighbour() independantly and it seemed to be working but if someone finds something wrong with it then that feedback is welcome also.
Mainly though as I mentioned my problem is with actually building the main loop in the Prim() -method, and if there's any additional info needed I'm happy to provide it.
Thank you.
Edit: To clarify what my train of thought with the Prim() method is. What I want to do is first randomize the starting point in the graph. After that, I will find the closest neighbor to that starting point. Then we'll add the edge connecting those two points to the MST, and also add the vertices to the visited list for checking later, so that we won't form any loops in the graph.
Here's the error that gets thrown:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at Graph.findClosestNeighbour(graph.java:203)
at Graph.Prim(graph.java:179)
at MST.main(MST.java:49)
Line 203: return neighbour.get(0); in findClosestNeighbour()
Line 179: Edge e = findClosestNeighbour(startingVertex); in Prim()
Vertex startingVertex = edges.get(rnd.nextInt(G.returnVertexCount())).returnStartingVertex();
This uses the vertex count to index an edge list, mixing up vertices and edges.
// This is supposed to be the main loop to find the MST, but this is probably horribly wrong..
while (MST.size() < returnVertexCount()) {
Edge e = findClosestNeighbour(startingVertex);
MST.add(e);
visited.add(e.returnStartingVertex());
visited.add(e.returnEndingVertex());
edges.remove(e);
}
This shouldn't be passing the same startingVertex to findClosestNeighbour each time.
public Edge findClosestNeighbour(Vertex v) {
ArrayList<Edge> neighbours = new ArrayList<Edge>();
ArrayList<Edge> edges = graph;
for (int i = 0; i < edges.size() -1; ++i) {
if (edges.get(i).endPoint() == s.returnVertexID() && !visited(edges.get(i).returnEndingVertex())) {
neighbours.add(edges.get(i));
}
}
return neighbours.get(0); // This is the minimum weight edge in the list.
}
What is s here? This doesn't look like it's taking the edge weights into account. It's skipping the last edge, and it's only checking the ending vertex, when the edges are non-directional.
// Simple weighted graph representation
// Uses an Adjacency Linked Lists, suitable for sparse graphs /*undirected
9
A
B
C
D
E
F
G
H
I
A B 1
B C 2
C E 7
E G 1
G H 8
F H 3
F D 4
D E 5
I F 9
I A 3
A D 1
This is the graph i used saved as graph.txt
*/
import java.io.*;
import java.util.Scanner;
class Heap
{
private int[] h; // heap array
private int[] hPos; // hPos[h[k]] == k
private int[] dist; // dist[v] = priority of v
private int MAX;
private int N; // heap size
// The heap constructor gets passed from the Graph:
// 1. maximum heap size
// 2. reference to the dist[] array
// 3. reference to the hPos[] array
public Heap(int maxSize, int[] _dist, int[] _hPos)
{
N = 0;
MAX = maxSize;
h = new int[maxSize + 1];
dist = _dist;
hPos = _hPos;
}
public boolean isEmpty()
{
return N == 0;
}
public void siftUp( int k)
{
int v = h[k];
h[0] = 0;
dist[0] = Integer.MIN_VALUE;
//vertex using dist moved up heap
while(dist[v] < dist[h[k/2]]){
h[k] = h[k/2]; //parent vertex is assigned pos of child vertex
hPos[h[k]] = k;//hpos modified for siftup
k = k/2;// index of child assigned last parent to continue siftup
}
h[k] = v;//resting pos of vertex assigned to heap
hPos[v] = k;//index of resting pos of vertex updated in hpos
//display hpos array
/* System.out.println("\nThe following is the hpos array after siftup: \n");
for(int i = 0; i < MAX; i ++){
System.out.println("%d", hPos[i]);
}
System.out.println("\n Following is heap array after siftup: \n");
for (int i = 0; i < MAX; i ++ ){
System.out.println("%d" , h[i]);
}*/
}
//removing the vertex at top of heap
//passed the index of the smallest value in heap
//siftdown resizes and resorts heap
public void siftDown( int k)
{
int v, j;
v = h[k];
while(k <= N/2){
j = 2 * k;
if(j < N && dist[h[j]] > dist[h[j + 1]]) ++j; //if node is > left increment j child
if(dist[v] <= dist[h[j]]) break;//if sizeof parent vertex is less than child stop.
h[k] = h[j];//if parent is greater than child then child assigned parent pos
hPos[h[k]] = k;//update new pos of last child
k = j;//assign vertex new pos
}
h[k] = v;//assign rest place of vertex to heap
hPos[v] = k;//update pos of the vertex in hpos array
}
public void insert( int x)
{
h[++N] = x;//assign new vertex to end of heap
siftUp( N);//pass index at end of heap to siftup
}
public int remove()
{
int v = h[1];
hPos[v] = 0; // v is no longer in heap
h[N+1] = 0; // put null node into empty spot
h[1] = h[N--];//last node of heap moved to top
siftDown(1);//pass index at top to siftdown
return v;//return vertex at top of heap
}
}
class Graph {
class Node {
public int vert;
public int wgt;
public Node next;
}
// V = number of vertices
// E = number of edges
// adj[] is the adjacency lists array
private int V, E;
private Node[] adj;
private Node z;
private int[] mst;
// used for traversing graph
private int[] visited;
private int id;
// default constructor
public Graph(String graphFile) throws IOException
{
int u, v;
int e, wgt;
Node t;
FileReader fr = new FileReader(graphFile);
BufferedReader reader = new BufferedReader(fr);
String splits = " +"; // multiple whitespace as delimiter
String line = reader.readLine();
String[] parts = line.split(splits);
System.out.println("Parts[] = " + parts[0] + " " + parts[1]);
V = Integer.parseInt(parts[0]);
E = Integer.parseInt(parts[1]);
// create sentinel node
z = new Node();
z.next = z;
// create adjacency lists, initialised to sentinel node z
adj = new Node[V+1];
for(v = 1; v <= V; ++v)
adj[v] = z;
// read the edges
System.out.println("Reading edges from text file");
for(e = 1; e <= E; ++e)
{
line = reader.readLine();
parts = line.split(splits);
u = Integer.parseInt(parts[0]);
v = Integer.parseInt(parts[1]);
wgt = Integer.parseInt(parts[2]);
System.out.println("Edge " + toChar(u) + "--(" + wgt + ")--" + toChar(v));
// write code to put edge into adjacency matrix
t = new Node(); t.vert = v; t.wgt = wgt; t.next = adj[u]; adj[u] = t;
t = new Node(); t.vert = u; t.wgt = wgt; t.next = adj[v]; adj[v] = t;
}
}
// convert vertex into char for pretty printing
private char toChar(int u)
{
return (char)(u + 64);
}
// method to display the graph representation
public void display() {
int v;
Node n;
for(v=1; v<=V; ++v){
System.out.print("\nadj[" + toChar(v) + "] ->" );
for(n = adj[v]; n != z; n = n.next)
System.out.print(" |" + toChar(n.vert) + " | " + n.wgt + "| ->");
}
System.out.println("");
}
//use the breath first approach to add verts from the adj list to heap
//uses 3 arrays where array = # of verts in graph
//parent array to keep track of parent verts
// a dist matrix to keep track of dist between it and parent
//hpos array to track pos of vert in the heap
public void MST_Prim(int s)
{
int v, u;
int wgt, wgt_sum = 0;
int[] dist, parent, hPos;
Node t;
//declare 3 arrays
dist = new int[V + 1];
parent = new int[V + 1];
hPos = new int[V +1];
//initialise arrays
for(v = 0; v <= V; ++v){
dist[v] = Integer.MAX_VALUE;
parent[v] = 0;
hPos[v] = 0;
}
dist[s] = 0;
//d.dequeue is pq.remove
Heap pq = new Heap(V, dist, hPos);
pq.insert(s);
while (! pq.isEmpty())
{
// most of alg here
v = pq.remove();
wgt_sum += dist[v];//add the dist/wgt of vert removed to mean spanning tree
//System.out.println("\nAdding to MST edge {0} -- ({1}) -- {2}", toChar(parent[v]), dist[v], toChar[v]);
dist[v] = -dist[v];//mark it as done by making it negative
for(t = adj[v]; t != z; t = t.next){
u = t.vert;
wgt = t.wgt;
if(wgt < dist[u]){ //weight less than current value
dist[u] = wgt;
parent[u] = v;
if(hPos[u] == 0)// not in heap insert
pq.insert(u);
else
pq.siftUp(hPos[u]);//if already in heap siftup the modified heap node
}
}
}
System.out.print("\n\nWeight of MST = " + wgt_sum + "\n");
//display hPos array
/*System.out.println("\nhPos array after siftUp: \n");
for(int i = 0; i < V; i ++){
System.out.println("%d", hPos[i]);
}*/
mst = parent;
}
public void showMST()
{
System.out.print("\n\nMinimum Spanning tree parent array is:\n");
for(int v = 1; v <= V; ++v)
System.out.println(toChar(v) + " -> " + toChar(mst[v]));
System.out.println("");
}
}
public class PrimLists {
public static void main(String[] args) throws IOException
{
int s = 2;
String fname = "graph.txt";
Graph g = new Graph(fname);
g.display();
}
}