I've been asked to create a Java program, wherein I accept a predefined number of vertices first, and then all the edges which exist in the graph as number pairs.
My code is supposed to accept the edges, create the 'graph' and color all the vertices.
My problem is with the coloring. The method 'setColor' is supposed to accept the degree of the graph each time it is called. The getBiggestVertex method is supposed to return the vertex to be coloured. It is then colored.
For some reason however, when I display the colors of the vertices, I constantly get either 0 or 1 or -1.
I'm unable to figure out why I am getting this output, could someone please help?
Graph Class:
import java.util.ArrayList;
import java.util.Scanner;
public class Graph {
ArrayList <Vertex> vertices = new ArrayList<Vertex>();
public Graph(){
Scanner sc = new Scanner(System.in);
int noOfVertices = sc.nextInt();
for(int i = 0; i <noOfVertices; i++){
addVertex();
}
String input = sc.next();
while(!input.equals("-1")){
String vertex [] = input.split(",");
addEdge(vertices.get(Integer.parseInt(vertex[0])), vertices.get(Integer.parseInt(vertex[1])));
input = sc.next();
}
for(int i = 0; i<vertices.size(); i++){
getBiggestVertex().setColor(vertices.size());
}
}
public Vertex getBiggestVertex(){
Vertex bVertex = new Vertex(-1);
for(int i = 0; i < vertices.size(); i++){
Vertex v = vertices.get(i);
if(v.colour ==-1){
if(v.getDegree() > bVertex.getDegree()){
bVertex = v;
} else if(v.getDegree() == bVertex.getDegree()){
if(v.vertexNumber < bVertex.vertexNumber){
bVertex = v;
}
} else if(v.getDegree() < bVertex.getDegree()){
}
}
}
return bVertex;
}
public void addVertex(){
vertices.add(new Vertex(vertices.size()));
}
public Vertex getVertex(int index){
return vertices.get(index);
}
public void addEdge(Vertex v1, Vertex v2){
v1.addAdjacency(v2);
v2.addAdjacency(v1);
}
}
Vertex Class:
import java.util.LinkedList;
public class Vertex {
int vertexNumber, colour;
LinkedList <Vertex> adjacencies = new LinkedList<Vertex>();
public Vertex(int vertexNum){
vertexNumber = vertexNum;
colour = -1;
}
public void addAdjacency(Vertex v){
adjacencies.add(v);
}
public boolean isAdjacent(Vertex v){
boolean adj = false;
for(int i = 0; i < adjacencies.size(); i++){
if(adjacencies.get(i) == v){
adj = true;
}
}
return adj;
}
public int getDegree(){
return adjacencies.size();
}
public void setColor(int degree){
int [] used = new int[degree];
for(int i = 0; i < adjacencies.size(); i++){
int c = adjacencies.get(i).colour;
System.out.println("Color of " + i + " = " + c);
used[c+1] = 1;
}
int unusedColor = 0;
while(used[unusedColor] == 1){
unusedColor ++;
}
colour = unusedColor;
}
}
I assume that -1 represents a vertex color not yet defined.
There are several issues with your code, most of which center around setColor method:
When checking the colors of adjacent vertices, the range of color codes is shifted by 1 to serve as indices into the usage marker array used. However, after having visited all neighbours the first color you test for is 0.
This process colors a vertex that only has uncolored neighbours with 1.
In case all neighbours have been colored, the assigned color will be 0.
Moreover in getBiggestVertex, the condition (v.vertexNumber < bVertex.vertexNumber) will never fire for vertices with an outdegree of 0 when all remaining vertices without assigned colors have outdegree 0 ( bVertex is initialised with the minimal vertex number of -1 and will never be reassigned ).
That means in particular that you may produce paths of vertices of the same color. Notably the following graph will be given an invalid colouring :
4,5
4,6
4,7
4,3
3,8
3,9
3,2
2,10
2,1
9,2
results in the colouring
c(1) = -1
c(2) = 1
c(3) = 1
c(4) = 1
c(5) = -1
c(6) = -1
c(7) = -1
c(8) = -1
c(9) = 0
c(10) = -1
c(11) = -1
where node 3 would need a new color 2 and -1 is an invalid color (which may be construed ex post as valid, of course).
Rectify the code by
maintaining bidirectional adjacencies (so a,b implies that a is adjacent to b and vice versa )
writing used[c] instead of used[c+1].
or check the colors of predecessor vertices as well.
In addition to the flawed color assignment, consider the following suggestions to improve your code:
The max degree is a property of the graph and thus should be a property of the graph class. Thus you do not need to allocate the worst case degree of the current number of vertices - 1 for the used array in setColor.
The node(s) with the highest degree in the graph need not be recomputed from scratch on every use but may be a property of the graph class as well
Taking the previous advice one step further, you may sort the vertices of the graph by decreasing degree before the colouring process storing this list. The should relieve you from the repeated calls to getBiggestVertex, you visit the nodes in the same order as they appear in the list.
Related
I wrote an algorithms for testing graph bipartitness for Graph Algorithms course on edX (initially available on Coursera) and it fails on one of their test cases.
I gave it a thought and cannot find so far what might I be missing, I use BFS traversal to color nodes to test for bipartitness, it works on a few simple test cases and on 17 of 28 test cases on edX.
private static final int WHITE = -1;
private static final int BLACK = -2;
private static final int START_INDEX = 0;
static boolean isBipartite(ArrayList<Integer>[] adj) { // an array of lists of neighbors
int[] colors = new int[adj.length];
boolean[] visited = new boolean[adj.length];
colors[START_INDEX] = WHITE;
Queue<Integer> queue = new LinkedList<>();
// start with some node
queue.add(START_INDEX);
while (!queue.isEmpty()) {
int node = queue.poll();
ArrayList<Integer> neighbors = adj[node];
for (int neighbor : neighbors) {
if (!visited[neighbor]) {
if (node != neighbor) {
// add for traversal and color with an opposite color
queue.add(neighbor);
colors[neighbor] = colors[node] == WHITE ? BLACK : WHITE;
} else {
// self cycle will always be odd
return false;
}
} else {
// return immediately if encountered an already colored node
// with the same color, there is an odd cycle
if (colors[node] == colors[neighbor]) {
return false;
}
}
}
visited[node] = true;
}
// final check of u and v colors for all edges
for (int u = 0; u < adj.length; u++) {
for (int i = 0; i < adj[u].size(); i++) {
int v = adj[u].get(i);
if (colors[u] == colors[v]) {
return false;
}
}
}
return true;
}
Any suggesting what could I be missing in my algorithm?
Also without the final check my algorithm would fail on the 3rd test case out of 28 (I do not see the inputs), even though I don't understand why - I should already be finding the odd cycles in the main for loop.
Please help.
Some of the sample graphs I tested myself, the 1st is not bipartite, the 2nd is bipartite.
As has been noted in the comments, you assume that every node is reachable from the starting node. The good news is that this is quite easy to fix. Define an enum Colors of three values: NoColor, Black, and White. The pseudocode goes as follows:
Input: graph G with nodes integers from 0 to n - 1
Initialise array colors of length n with all values set to NoColor;
for each `i` from `0` to `n - 1`, do {
if colors[i] = NoColor then {
Initialise q to an empty queue (or stack - whatever floats your boat);
push i onto queue;
colors[i] <- Black;
while q is not empty do {
pop k off of q;
for each neighbour i of k such that colors[i] = NoColor do
colors[i] <- the opposite color of colors[k];
push i onto q;
}
}
}
}
This gives you the 2-coloring, if the coloring exists. In this case, you'll want to verify that it is in fact a 2-coloring to check if the graph is bipartite.
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'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();
}
}
Given the adjacency matrix of a graph, I need to obtain the chromatic number (minimum number of colours needed to paint every node of a graph so that adjacent nodes get different colours).
Preferably it should be a java algorithm, and I don't care about performance.
Thanks.
Edit:
recently introduced a fix so the answer is more accurately. now it will recheck his position with his previous positions.
Now a new question comes up. Which will be better to raise his 'number-color'? the node in which i am standing, or the node i am visiting (asking if i am adjacent to it)?
public class Modelacion {
public static void main(String args[]) throws IOException{
// given the matrix ... which i have hidden the initialization here
int[][] matriz = new int[40][40];
int color[] = new int[40];
for (int i = 0 ; i<40;i++)
color[i]=1;
Cromatico c = new Cromatico(matriz, color);
}
}
import java.io.IOException;
public class Cromatico {
Cromatico(int[][]matriz, int[] color, int fila) throws IOException{
for (int i = 0; i<fila;i++){
for (int j = 0 ; j<fila;j++){
if (matriz[i][j] == 1 && color[i] == color [j]){
if (j<i)
color [i] ++;
else
color [j] ++;
}
}
}
int numeroCromatico = 1;
for (int k = 0; k<fila;k++){
System.out.print(".");
numeroCromatico = Math.max(numeroCromatico, color[k]);
}
System.out.println();
System.out.println("el numero cromatico del grafo es: " + numeroCromatico);
}
}
Finding the chromatic number of a graph is NP-Complete (see Graph Coloring). It is NP-Complete even to determine if a given graph is 3-colorable (and also to find a coloring).
The wiki page linked to in the previous paragraph has some algorithms descriptions which you can probably use.
btw, since it is NP-Complete and you don't really care about performance, why don't you try using brute force?
Guess a chromatic number k, try all possibilities of vertex colouring (max k^n possibilities), if it is not colorable, new guess for chromatic number = min{n,2k}. If it is k-colorable, new guess for chromatic number = max{k/2,1}. Repeat, following the pattern used by binary search and find the optimal k.
Good luck!
And to answer your edit.
Neither option of incrementing the color will work. Also, your algorithm is O(n^2). That itself is enough to tell it is highly likely that your algorithm is wrong, even without looking for counterexamples. This problem is NP-Complete!
Super slow, but it should work:
int chromaticNumber(Graph g) {
for (int ncolors = 1; true; ncolors++) {
if (canColor(g, ncolors)) return ncolors;
}
}
boolean canColor(Graph g, int ncolors) {
return canColorRemaining(g, ncolors, 0));
}
// recursive routine - the first colors_so_far nodes have been colored,
// check if there is a coloring for the rest.
boolean canColorRemaining(Graph g, int ncolors, int colors_so_far) {
if (colors_so_far == g.nodes()) return true;
for (int c = 0; c < ncolors; c++) {
boolean ok = true;
for (int v : g.adjacent(colors_so_far)) {
if (v < colors_so_far && g.getColor(v) == c) ok = false;
}
if (ok) {
g.setColor(colors_so_far, c);
if (canColorRemaining(g, ncolors, colors_so_far + 1)) return true;
}
}
return false;
}