Index out of bounds error for DAG - java

I'm writing a program to find the longest path for a DAG with input from standard in.I finally got it to compile, with it saying it is using unchecked or unsafe operations due to my Array list, but I am getting an index out of bounds error and it feels like I have tried changing every loop I must be missing something, thanks in advanced for any tips.
Here is my code:
import java.io.*;
import java.util.*;
public class countLongPaths
{
static final int NINF = Integer.MIN_VALUE;
public class AdjListNode
{
private int v;
private int weight;
AdjListNode(int inV, int inW)
{
v = inV;
weight = inW;
}
int getV()
{
return v;
}
int getWeight()
{
return weight;
}
}//end of adj list class
public class Graph
{
private int V;
private LinkedList<AdjListNode>adj[];
//set up graph with given number of verticies
Graph(int v)
{
V=v;
adj = new LinkedList[V];
for (int i = 0; i < v; ++i)
adj[i] = new LinkedList<AdjListNode>();
}
//function to add edges to graph
void addEdge(int u, int v, int weight)
{
AdjListNode node = new AdjListNode(v,weight);
adj[u].add(node);// Add v to u's list
}
//function to set order to go through vertices
void setOrder(int v, Boolean visited[], Stack stack)
{
//Set node to visited when on it
visited[v] = true;
Integer i;
//for all nodes connected to current repeat
Iterator<AdjListNode> it = adj[v].iterator();
while (it.hasNext())
{
AdjListNode node =it.next();
if (!visited[node.getV()])
setOrder(node.getV(), visited, stack);
}
//Once done with current add it to the stack
stack.push(new Integer(v));
}
//function to find longest paths from s
int longestPath()
{
Stack stack = new Stack();
int LP[] = new int[V];
//set all vertices to unvisited
Boolean visited[] = new Boolean[V];
for(int i = 1; i <= V; i++)
visited[i] = false;
//call set order function from each vertex
for (int i = 1; i <= V; i++)
{
if(visited[i] == false)
setOrder(i, visited, stack);
}
//initialize distaces to all verices as negative infinity
//set distace to source to 0
LP[1] = 0;
for(int i = 2; i <= V; i++)
LP[i] = NINF;
//go through vertices in order
while(stack.empty() == false)
{
int u = (int)stack.pop();
//update LP for adj vertices
Iterator<AdjListNode> it;
if (LP[u] != NINF)
{
it = adj[u].iterator();
while (it.hasNext())
{
AdjListNode i = it.next();
if(LP[i.getV()] < LP[u] + i.getWeight())
LP[i.getV()] = LP[u] + i.getWeight();
}
}
}
return LP[V];
}
}//end of graph class
//Method to make a new graph
public Graph newGraph(int number)
{
return new Graph(number);
}
public static void main(String[]args)
{
countLongPaths n = new countLongPaths();
int GN = 0;
int count = 1;
Scanner scan = new Scanner(System.in);
GN = scan.nextInt();
while (count<= GN)
{
int N = 0;// nodes
int M = 0;//edges
N = scan.nextInt();
M = scan.nextInt();
//setup a new graph
Graph g = n.newGraph(N);
//set edges for new graph
for(int i = 1; i <= M; i ++)
{
int I = scan.nextInt();
int J = scan.nextInt();
int W = scan.nextInt();
g.addEdge(I, J, W);
}
int dist = 0;
dist = g.longestPath();
System.out.println("graph number: " + count);
System.out.println("longest path: " + dist);
System.out.println("number of longest paths: ");
System.out.println();
count++;
}//end of while
}//end main
}//end program
EDIT 1
with current code this is the error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
at countLongPaths$Graph.<init>(countLongPaths.java:36)
at countLongPaths.newGraph(countLongPaths.java:108)
at countLongPaths.main(countLongPaths.java:127)

As your stack trace says, the exception occurs in your Graph class constructor.
More specifically it happens inside the only line in your loop:
adj = new LinkedList[V];
for (int i = 0; i <= v; ++i)
adj[i] = new LinkedList<AdjListNode>();
Assuming you've meant both lowercase v and uppercase V to be the same variable, you're defining an array of size V which is indexed from 0 to V-1, but you're running on it from 0 to V (your condition is i <= V), which is why you're getting an IndexOutOfBoundsException.
Simply change the loop's condition (remove the =):
for (int i = 0; i < v; ++i)

Related

Find all connected components and their sizes in a graph

I'm trying to find all connected components and their sizes in a graph. I don't know why, but the size is always 0. Maybe something is wrong in the method.
This is the problem that I am trying to solve. https://www.codechef.com/LRNDSA08/problems/FIRESC
public class B {
static void dfs(int s, int v, boolean[] visited, ArrayList<ArrayList<Integer>> adj) {
s++;
visited[v] = true;
for (int u : adj.get(v)) {
if (!visited[u]) {
dfs(s, u, visited, adj);
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
StringBuilder str = new StringBuilder();
int t = sc.nextInt();
for (int xx = 0; xx < t; xx++) {
int n = sc.nextInt();
int m = sc.nextInt();
ArrayList<ArrayList<Integer>> arr = new ArrayList<>();
for (int i = 0; i < n; i++) {
arr.add(new ArrayList<Integer>());
}
boolean[] visited = new boolean[n];
Arrays.fill(visited, false);
for (int i = 0; i < m; i++) {
int a = sc.nextInt();
int b = sc.nextInt();
a--;
b--;
arr.get(a).add(b);
arr.get(b).add(a);
}
long ways = 1;
int groups = 0;
for (int i = 0; i < n; i++) {
if (visited[i])
continue;
int size = 0;
dfs(size, i, visited, arr);
groups++;
ways *= size;
ways %= 1000000007;
}
System.out.println(groups + " " + ways);
}
}
}
You know size is passed as value and not as reference. So it won't get updated after you return from the call. One thing you could do is define a single element array like
int[] size = new int[1];
and modify your dfs like:
static void dfs(int[] s, int v, boolean[] visited, ArrayList<ArrayList<Integer>> adj) {
s[0]++;
visited[v] = true;
for (int u : adj.get(v)) {
if (!visited[u]) {
dfs(s, u, visited, adj);
}
}
}
Then your result will be in size[0] which you can use to update ways like ways *= size[0]
Or you could modify dfs to return size which is a cleaner way to get the size like below:
static int dfs(int v, boolean[] visited, ArrayList<ArrayList<Integer>> adj) {
visited[v] = true;
int sz = 1;
for (int u : adj.get(v)) {
if (!visited[u]) {
sz += dfs(u, visited, adj);
}
}
return sz;
}
And it seems like you have a misconception on how variables in Java work (see). Incrementing an int variable that resides on one lair of the stack would not affect a variable on another stack lair. That's why the size is always 0.
The following solution passes base test on CodeChef:
public class CountComponents {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int testCases = sc.nextInt();
for (int i = 0; i < testCases; i++) {
EmployeeGraph graph = parseGraph(sc);
graph.countComponentsAndComponentSizes();
}
}
public static EmployeeGraph parseGraph(Scanner sc) {
int employeeCount = sc.nextInt();
int connectionsCount = sc.nextInt();
boolean[][] adjacencyMatrix = new boolean[employeeCount][employeeCount];
for (int i = 0; i < connectionsCount; i++) {
int row = sc.nextInt() - 1;
int col = sc.nextInt() - 1;
adjacencyMatrix[row][col] = true;
adjacencyMatrix[col][row] = true;
}
return new EmployeeGraph(adjacencyMatrix);
}
}
class EmployeeGraph {
public static final int BILLION_SEVEN = 1_000_000_007;
private boolean[][] adjacencyMatrix;
public EmployeeGraph(boolean[][] adjacencyMatrix) {
this.adjacencyMatrix = adjacencyMatrix;
}
public void countComponentsAndComponentSizes() {
boolean[] visited = new boolean[adjacencyMatrix.length];
int componentCount = 0;
int waysToChooseCaptain = 1;
for (int row = 0; row < adjacencyMatrix.length; row++) {
if (!visited[row]) {
componentCount++;
waysToChooseCaptain = (waysToChooseCaptain % BILLION_SEVEN) * dfs(visited, row);
}
}
System.out.println(componentCount + " " + waysToChooseCaptain % BILLION_SEVEN);
}
public int dfs(boolean[] visited, int row) {
visited[row] = true; // marking the current employee as visited
int size = 1; // this component consists at least from 1 employee
for (int col = 0; col < adjacencyMatrix.length; col++) {
if (adjacencyMatrix[row][col] && !visited[col]) {
size += dfs(visited, col);
}
}
return size;
}
}

How to list connected vertices of a non-connected graph

example - there is an unconnected graph with vertices A - B - C - D and E - F - G. (a hyphen means that they are connected). The code below is using depth-first traversal, I need to modify it to display all connected vertices. eg:
list0: ABCD
list1: EFG
etc...
I don't understand how to implement this.
public class Graph {
private final int MAX_VERTS = 20;
private Vertex vertexList[];
private int matrix[][];
private int countV;
private StackX theStack;
// ------------------------------------------------------------
public Graph() {
vertexList = new Vertex[MAX_VERTS];
matrix = new int[MAX_VERTS][MAX_VERTS];
countV = 0;
for (int x = 0; x < MAX_VERTS; x++)
for (int y = 0; y < MAX_VERTS; y++)
matrix[x][y] = 0;
theStack = new StackX();
}
// -------------------------------------------------------------
public void addVertex(char label) {
vertexList[countV++] = new Vertex(label);
}
// -------------------------------------------------------------
public void addEdge(int x, int y) {
matrix[x][y] = 1;
matrix[y][x] = 1;
}
// -------------------------------------------------------------
public void displayVertex(int v) {
System.out.print(vertexList[v].label);
}
public void dfs() {
vertexList[0].wasVisited = true;
displayVertex(0);
theStack.push(0);
while (!theStack.isEmpty()) {
int v = getUnvisitedVertex(theStack.peek());
if (v == -1)
theStack.pop();
else
{
vertexList[v].wasVisited = true;
displayVertex(v);
theStack.push(v);
}
}
for (int j = 0; j < countV; j++)
vertexList[j].wasVisited = false;
}
// ------------------------------------------------------------
public int getUnvisitedVertex(int vertex) {
for (int j = 0; j < countV; j++)
if (matrix[vertex][j] == 1 && !vertexList[j].wasVisited) {
return j;
}
return -1;
}
}
Your DFS does not need to modified. It needs to be put inside a loop so that each pass will discover one of the lists of connected nodes that your are looking for
LOOP
Select arbitrary vertex
DFS, saving each visited vertex in list.
LOOP over visited vertices
remove from graph
LOOP END
IF all vertices removed
BREAK out of loop
Start new list
LOOP END
Output lists

BFS using Adjecency Matrix

Question to find Bfs path ,, i am able to code bfs path if the graph have vertices marked as 0,1,2,3,4,,like this
But can't able to apply adjacency matrix how to solve bfs for graph like 5,10,15,20
attached images what i have coded
solution
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Bfs {
public static void bfsTraversal(int[][] adjMatrix) {
Queue<Integer> pendingVertices = new LinkedList<>();
boolean[] visited = new boolean[adjMatrix.length];
visited[0] = true;
pendingVertices.add(0);
while (!pendingVertices.isEmpty()) {
int currentVertex = pendingVertices.poll();
System.out.print(currentVertex + " ");
for (int i = 0; i < adjMatrix.length; i++) {
if (adjMatrix[currentVertex][i] == 1 && !visited[i]) {
pendingVertices.add(i);
visited[i] = true;
}
}
}
}
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int v = s.nextInt();
int e = s.nextInt();
int[][] adjMatrix = new int[v][v];
for (int i = 0; i < e; i++) {
int v1 = s.nextInt();
int v2 = s.nextInt();
adjMatrix[v1][v2] = 1;
adjMatrix[v2][v1] = 1;
}
bfsTraversal(adjMatrix);
}
}
Click here for Question for bfs like vertices 0,1,2,3,4...
Click here for ,How i want to solve this for bfs like vertices 5,10,15,20...
And i want to do the same for graph like this ,,can't get logic
Solved by mapping the input with 0,1,2,3.... and maintained a reverseMap
Click here to view the Solution
If you know the range of the numbers, you can let the numbers 5, 10, 15 and 20 be the IDs of the nodes and store the indices of the nodes in a seperate array. Suppose the name of the array is IndexLookupArray, if you want to lookup the index of a node with ID x you can find it in IndexLookupArray[x]. And the rest of the code should be the same. If the range of the numbers is unknown or if it's too big to fit in an array, you can store the indices in a hash map for example and do the same thing.
You can write something like this:
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Bfs {
public static void bfsTraversal(int[][] adjMatrix) {
Queue<Integer> pendingVertices = new LinkedList<>();
boolean[] visited = new boolean[adjMatrix.length];
visited[0] = true;
pendingVertices.add(0);
while (!pendingVertices.isEmpty()) {
int currentVertex = pendingVertices.poll();
System.out.print(currentVertex + " ");
for (int i = 0; i < adjMatrix.length; i++) {
if (adjMatrix[currentVertex][i] == 1 && !visited[i]) {
pendingVertices.add(i);
visited[i] = true;
}
}
}
}
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int idx = 0;
int range = s.nextInt();
int v = s.nextInt();
int e = s.nextInt();
int[] IndexLookupArray = new int[range + 1]; // range + 1 since IndexLookupArray[range] should be accessible.
int[][] adjMatrix = new int[v][v];
Arrays.fill(IndexLookupArray, 0, range + 1, -1);
for (int i = 0; i < e; i++) {
int v1 = s.nextInt();
if (IndexLookupArray[v1] == -1)
{
IndexLookupArray[v1] = idx;
idx++;
}
v1 = IndexLookupArray[v1];
int v2 = s.nextInt();
if (IndexLookupArray[v2] == -1)
{
IndexLookupArray[v2] = idx;
idx++;
}
v2 = IndexLookupArray[v2];
adjMatrix[v1][v2] = 1;
adjMatrix[v2][v1] = 1;
}
bfsTraversal(adjMatrix);
}
}

Using Depth-First Search in JAVA program instead of Breadth-First Search

I have a JAVA program where I am creating graphs and I have a Breadth-First Search but I would like to change it to Depth First Search. What changes should I make in a code? Thanks for help in advance.
public class ConnectedComponents
{
static final int MAXV = 100;
static boolean processed[] = new boolean[MAXV];
static boolean discovered[] = new boolean[MAXV];
static int parent[] = new int[MAXV];
static void bfs(CCGraph g, int start)
{
Queue<Integer> q = new LinkedList<Integer>();
int i, v;
q.offer(start);
discovered[start] = true;
while (!q.isEmpty())
{
v = q.remove();
process_vertex(v);
processed[v] = true;
for (i = g.degree[v] - 1; i >= 0; i--)
{
if (!discovered[g.edges[v][i]])
{
q.offer(g.edges[v][i]);
discovered[g.edges[v][i]] = true;
parent[g.edges[v][i]] = v;
}
}
}
}
I think you should understand the difference between depth first search and breadth first search. The code for depth first search goes as follows:
public class ConnectedComponents
{
static final int MAXV = 100;
static boolean processed[] = new boolean[MAXV];
static boolean discovered[] = new boolean[MAXV];
static int parent[] = new int[MAXV];
static void dfs(CCGraph g, int vertex)
{
discovered[vertex] = true;
for (i = g.degree[vertex] - 1; i >= 0; i--)
{
if (!discovered[g.edges[vertex][i]])
{
parent[g.edges[v][i]]=vertex;
dfs(g.edges[v][i]]);
}
}
}
}
The basic difference is the order by which vertexes are tested. While BFS uses queue (FIFO: First In First Out), DFS use stack (LIFO: Last In First Out).
You could implement stack using LinkedList:
LinkedList<Integer> stack = new LinkedList<Integer>();
stack.pop(); //returns the top of the stack
For more information please post mcve including test data.
Full code of the program. The goal is to change bfs to dfs.
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
class CCGraph
{
static final int MAXV = 100;
static final int MAXDEGREE = 50;
public int edges[][] = new int[MAXV + 1][MAXDEGREE];
public int degree[] = new int[MAXV + 1];
public int nvertices;
public int nedges;
CCGraph()
{
nvertices = nedges = 0;
for (int i = 1; i <= MAXV; i++)
degree[i] = 0;
}
void read_CCGraph(boolean directed)
{
int x, y;
Scanner sc = new Scanner(System.in);
System.out.println("Enter the number of vertices: ");
nvertices = sc.nextInt();
System.out.println("Enter the number of edges: ");
int m = sc.nextInt();
System.out.println("Enter the edges: <from> <to>");
for (int i = 1; i <= m; i++)
{
x = sc.nextInt();
y = sc.nextInt();
insert_edge(x, y, directed);
}
sc.close();
}
void insert_edge(int x, int y, boolean directed)
{
if (degree[x] > MAXDEGREE)
System.out.printf(
"Warning: insertion (%d, %d) exceeds max degree\n", x, y);
edges[x][degree[x]] = y;
degree[x]++;
if (!directed)
insert_edge(y, x, true);
else
nedges++;
}
void print_CCGraph()
{
for (int i = 1; i <= nvertices; i++)
{
System.out.printf("%d: ", i);
for (int j = degree[i] - 1; j >= 0; j--)
System.out.printf(" %d", edges[i][j]);
System.out.printf("\n");
}
}
}
public class ConnectedComponents
{
static final int MAXV = 100;
static boolean processed[] = new boolean[MAXV];
static boolean discovered[] = new boolean[MAXV];
static int parent[] = new int[MAXV];
static void bfs(CCGraph g, int start)
{
LinkedList<Integer> q = new LinkedList<Integer>();
int i, v;
q.offer(start);
discovered[start] = true;
while (!q.isEmpty())
{
v = q.remove();
process_vertex(v);
processed[v] = true;
for (i = g.degree[v] - 1; i >= 0; i--)
{
if (!discovered[g.edges[v][i]])
{
q.offer(g.edges[v][i]);
discovered[g.edges[v][i]] = true;
parent[g.edges[v][i]] = v;
}
}
}
}
static void initialize_search(CCGraph g)
{
for (int i = 1; i <= g.nvertices; i++)
{
processed[i] = discovered[i] = false;
parent[i] = -1;
}
}
static void process_vertex(int v)
{
System.out.printf(" %d", v);
}
static void connected_components(CCGraph g)
{
int c;
initialize_search(g);
c = 0;
for (int i = 1; i <= g.nvertices; i++)
{
if (!discovered[i])
{
c++;
System.out.printf("Component %d:", c);
bfs(g, i);
System.out.printf("\n");
}
}
}
static public void main(String[] args)
{
CCGraph g = new CCGraph();
g.read_CCGraph(false);
g.print_CCGraph();
connected_components(g);
}
}

Why doesn't Dijkstra's algorithm work as it should for given graph?

I have the following code, Dijkstra's algorithm, that I made using Wikipedia's article on the algorithm.
For the given graph (see image) and starting node (1), it returns 5 as distance to node (4), which is obviously false. However, when going from node (4), it returns 4 as distance to (1), which is correct. What is wrong in my code?
//source = starting point, adj[] = adjacency list
private static int dijkstra (int source, ArrayList<Road>[] adj) {
HashSet<Integer> vertices = new HashSet<>();
int[] dist = new int[adj.length];
int[] prev = new int[adj.length];
for (int i = 0; i < adj.length; i++) {
dist[i] = Integer.MAX_VALUE;
prev[i] = Integer.MAX_VALUE;
vertices.add(i);
}
dist[source] = 0;
while (!vertices.isEmpty()) {
int current = Integer.MAX_VALUE;
for (int v: vertices) {
if (dist[v] < current) {
current = v;
}
}
vertices.remove(current);
for (Road v: adj[current]) {
int alt = dist[current] + v.distance;
if (alt < dist[v.end]) {
dist[v.end] = alt;
prev[v.end] = current;
}
}
}
}
class Road {
int end;
int distance;
}
//This loop builds adjacency list from input such as "1 3 2", where 1 represents
// starting node, 3 represents end node and 2 represents weight of that edge.
//start and end values are decremented in order to be 0-indexed
for (int i = 0; i < M; i++) {
int start = in.nextInt() - 1;
int end = in.nextInt() - 1 ;
int dist = in.nextInt();
adj[start].add(new Road(end, dist));
adj[end].add(new Road(start, dist));
}
This piece of code is causing the error:
int current = Integer.MAX_VALUE;
for (int v: vertices) {
if (dist[v] < current) {
current = v;
}
}
I assume it's supposed to search the unvisited node that has the shortest path from the start-vertex. But this should look rather like this:
int currentPathLen = Integer.MAX_VALUE, current = -1;
for (int v: vertices) {
if (dist[v] < currentPathLen) {
current = v;
currentPathLen = dist[current];
}
}

Categories