DBSCAN not working properly - java

I am implementing DBSCAN in java. I have followed the algorithm given over here (Wikipedia). I think I have it right but for some reason only 1 cluster is formed.
The Java code looks like
ArrayList<ArrayList<Node>> dbcluster = new ArrayList<>();
ArrayList<Node> points; // this contains my data assume
int min =10, esp =50;
int clustcount =0;
for(int i=0;i<points.size();i++){
Node tempdb = points.get(i);
if(tempdb.visited==false){
tempdb.visited=true;
ArrayList<Node> myNeighbors = getNeigbhors(tempdb,points, esp);
if(myNeighbors.size() < min){
tempdb.noise = true;
}else{
//ArrayList<Node> tempclust = new ArrayList<>();
dbcluster.add(new ArrayList<Node>());
expandCluster(tempdb,points,myNeighbors,dbcluster,esp,min,clustcount);
clustcount++;
}
}
public static ArrayList<Node> getNeigbhors(Node p ,ArrayList<Node> data,int esp){
ArrayList<Node> tempReturn = new ArrayList<>();
for(int i=0;i<data.size();i++){
Node temptemp = data.get(i);
if(p.x != temptemp.x && p.y !=temptemp.y){
double distance =Math.sqrt(((p.x - temptemp.x)*(p.x - temptemp.x))+((p.y - temptemp.y)*(p.y - temptemp.y)));
if(distance <=esp){
tempReturn.add(temptemp);
}
}
}
return tempReturn;
}
public static void expandCluster(Node p, ArrayList<Node> data, ArrayList<Node> N, ArrayList<ArrayList<Node>> allCluster,int esp, int min,int clustcount){
//ArrayList<Node> tempSmallClust = new ArrayList<>();
//tempSmallClust.add(p);
allCluster.get(clustcount).add(p);
for(int i=0;i<N.size();i++){
Node tempP = N.get(i);
if(tempP.visited == false){
tempP.visited=true;
ArrayList<Node> tempNewNeighbors = new ArrayList<>();
tempNewNeighbors = getNeigbhors(tempP, data, esp);
if(tempNewNeighbors.size() >= min){
ArrayList<Node> tempN=new ArrayList<>();
tempN=mergeNeighbors(N, tempNewNeighbors);
N = new ArrayList<>();
N=tempN;
}
}
if(!checkInCluster(tempP,allCluster)) {
allCluster.get(clustcount).add(tempP);
}
}
//return tempSmallClust;
}
public static boolean checkInCluster(Node p, ArrayList<ArrayList<Node>> allCluster){
for(int i=0;i<allCluster.size();i++){
ArrayList<Node> tempList = allCluster.get(i);
if(tempList.contains(p)){
return true;
}
}
return false;
}
public static ArrayList<Node> mergeNeighbors(ArrayList<Node> N,ArrayList<Node> NewN){
ArrayList<Node> tmpR = N;
for(int i=0;i<NewN.size();i++){
if(!N.contains(NewN.get(i))){
tmpR.add(NewN.get(i));
}
}
return tmpR;
}
The node class is simple with int x int y and boolean noise and visited.
the data is provided here here data

Your data is uniform distributed.
There are no clusters in this data set.
IMHO the correct of putting everything in one cluster (if eps too high and minpts too low) is correct, or putting everything into noise (if eps and minpts set appropriately).
So maybe it's not an implementation error, but your data is not appropriate.

Related

Shortest Path with Dijkstra

I using this exact code for this. I modified it a little. So far I added a start and end node index to the calculateShortestDistances() method. Also the path ArrayList for collecting the path node indexes. Also: new to Java...
How do I collect the indexes of nodes in the path ArrayList?
I just can't come up with the solution on a level that I am not even positive this code could do what I want. I only have intuition on my side and little time.
What I tried:
Adding the nextNode value to the list then removing it if it was not
a shorter distance.
Adding the neighbourIndex to the list then removing it if it was not a shorter distance.
I made a Path.java with ArrayList but that was went nowhere (it was a class with a public variable named path) but it went nowhere.
Main.java:
public class Main {
public static void main(String[] args) {
Edge[] edges = {
new Edge(0, 2, 1), new Edge(0, 3, 4), new Edge(0, 4, 2),
new Edge(0, 1, 3), new Edge(1, 3, 2), new Edge(1, 4, 3),
new Edge(1, 5, 1), new Edge(2, 4, 1), new Edge(3, 5, 4),
new Edge(4, 5, 2), new Edge(4, 6, 7), new Edge(4, 7, 2),
new Edge(5, 6, 4), new Edge(6, 7, 5)
};
Graph g = new Graph(edges);
g.calculateShortestDistances(4,6);
g.printResult(); // let's try it !
System.out.println(g.path);
}
}
Graph.java:
This is the Graph.java file. Here I added a sAt and eAt variable, so I can tell it what path I am after. Also I created a public path ArrayList, where I intend to collect the path.
import java.util.ArrayList;
// now we must create graph object and implement dijkstra algorithm
public class Graph {
private Node[] nodes;
private int noOfNodes;
private Edge[] edges;
private int noOfEdges;
private int sAt;
private int eAt;
public ArrayList<Integer> path = new ArrayList<>();
public Graph(Edge[] edges) {
this.edges = edges;
// create all nodes ready to be updated with the edges
this.noOfNodes = calculateNoOfNodes(edges);
this.nodes = new Node[this.noOfNodes];
for (int n = 0; n < this.noOfNodes; n++) {
this.nodes[n] = new Node();
}
// add all the edges to the nodes, each edge added to two nodes (to and from)
this.noOfEdges = edges.length;
for (int edgeToAdd = 0; edgeToAdd < this.noOfEdges; edgeToAdd++) {
this.nodes[edges[edgeToAdd].getFromNodeIndex()].getEdges().add(edges[edgeToAdd]);
this.nodes[edges[edgeToAdd].getToNodeIndex()].getEdges().add(edges[edgeToAdd]);
}
}
private int calculateNoOfNodes(Edge[] edges) {
int noOfNodes = 0;
for (Edge e : edges) {
if (e.getToNodeIndex() > noOfNodes)
noOfNodes = e.getToNodeIndex();
if (e.getFromNodeIndex() > noOfNodes)
noOfNodes = e.getFromNodeIndex();
}
noOfNodes++;
return noOfNodes;
}
public void calculateShortestDistances(int startAt, int endAt) {
// node 0 as source
this.sAt = startAt;
this.eAt = endAt;
this.nodes[startAt].setDistanceFromSource(0);
int nextNode = startAt;
// visit every node
for (int i = 0; i < this.nodes.length; i++) {
// loop around the edges of current node
ArrayList<Edge> currentNodeEdges = this.nodes[nextNode].getEdges();
for (int joinedEdge = 0; joinedEdge < currentNodeEdges.size(); joinedEdge++) {
int neighbourIndex = currentNodeEdges.get(joinedEdge).getNeighbourIndex(nextNode);
// only if not visited
if (!this.nodes[neighbourIndex].isVisited()) {
int tentative = this.nodes[nextNode].getDistanceFromSource() + currentNodeEdges.get(joinedEdge).getLength();
if (tentative < nodes[neighbourIndex].getDistanceFromSource()) {
nodes[neighbourIndex].setDistanceFromSource(tentative);
}
}
}
// all neighbours checked so node visited
nodes[nextNode].setVisited(true);
// next node must be with shortest distance
nextNode = getNodeShortestDistanced();
}
}
// now we're going to implement this method in next part !
private int getNodeShortestDistanced() {
int storedNodeIndex = 0;
int storedDist = Integer.MAX_VALUE;
for (int i = 0; i < this.nodes.length; i++) {
int currentDist = this.nodes[i].getDistanceFromSource();
if (!this.nodes[i].isVisited() && currentDist < storedDist) {
storedDist = currentDist;
storedNodeIndex = i;
}
}
return storedNodeIndex;
}
// display result
public void printResult() {
String output = "Number of nodes = " + this.noOfNodes;
output += "\nNumber of edges = " + this.noOfEdges;
output += "\nDistance from "+sAt+" to "+eAt+":" + nodes[eAt].getDistanceFromSource();
System.out.println(output);
}
public Node[] getNodes() {
return nodes;
}
public int getNoOfNodes() {
return noOfNodes;
}
public Edge[] getEdges() {
return edges;
}
public int getNoOfEdges() {
return noOfEdges;
}
}
Addittionally here are the Edge.java and the Node.java classes.
Node.java:
import java.util.ArrayList;
public class Node {
private int distanceFromSource = Integer.MAX_VALUE;
private boolean visited;
private ArrayList<Edge> edges = new ArrayList<Edge>(); // now we must create edges
public int getDistanceFromSource() {
return distanceFromSource;
}
public void setDistanceFromSource(int distanceFromSource) {
this.distanceFromSource = distanceFromSource;
}
public boolean isVisited() {
return visited;
}
public void setVisited(boolean visited) {
this.visited = visited;
}
public ArrayList<Edge> getEdges() {
return edges;
}
public void setEdges(ArrayList<Edge> edges) {
this.edges = edges;
}
}
Edge.java
public class Edge {
private int fromNodeIndex;
private int toNodeIndex;
private int length;
public Edge(int fromNodeIndex, int toNodeIndex, int length) {
this.fromNodeIndex = fromNodeIndex;
this.toNodeIndex = toNodeIndex;
this.length = length;
}
public int getFromNodeIndex() {
return fromNodeIndex;
}
public int getToNodeIndex() {
return toNodeIndex;
}
public int getLength() {
return length;
}
// determines the neighbouring node of a supplied node, based on the two nodes connected by this edge
public int getNeighbourIndex(int nodeIndex) {
if (this.fromNodeIndex == nodeIndex) {
return this.toNodeIndex;
} else {
return this.fromNodeIndex;
}
}
}
I know it looks like a homework. Trust me it isn't. On the other hand I have not much time to finish it, that is why I do it at Sunday. Also I am aware how Dijkstra algorithm works, I understand the concept, I can do it on paper. But collecting the path is beyond me.
Thanks for Christian H. Kuhn's and second's comments I managed to come up with the code.
I modified it as follows (I only put in the relevant parts)
Node.java
Here I added a setPredecessor(Integer predecessor) and a getPredecessor() methods to set and get the value of the private variable predecessor (so I follow the original code's style too).
[...]
private int predecessor;
[...]
public int getPredecessor(){
return predecessor;
}
public void setPredecessor(int predecessor){
this.predecessor = predecessor;
}
[...]
Graph.java
Here I created the calculatePath() and getPath() methods. calculatePath() does what the commenters told me to do. The getPath() returns the ArrayLists for others to use.
[...]
private int sAt;
private int eAt;
private ArrayList<Integer> path = new ArrayList<Integer>();
[...]
public void calculateShortestDistances(int startAt, int endAt) {
[...]
if (tentative < nodes[neighbourIndex].getDistanceFromSource()) {
nodes[neighbourIndex].setDistanceFromSource(tentative);
nodes[neighbourIndex].setPredecessor(nextNode);
}
[...]
public void calculatePath(){
int nodeNow = eAt;
while(nodeNow != sAt){
path.add(nodes[nodeNow].getPredecessor());
nodeNow = nodes[nodeNow].getPredecessor();
}
}
public ArrayList<Integer> getPath(){
return path;
}
[...]
Main.java so here I can do this now:
[...]
Graph g = new Graph(edges);
g.calculateShortestDistances(5,8);
g.calculatePath();
String results = "";
ArrayList<Integer> path = g.getPath();
System.out.println(path);
[...]
I know it shows the path backwards, but that is not a problem, as I can always reverse it. The point is: I not only have the the distance from node to node, but the path through nodes too. Thank you for the help.

Why my Dijkstra's algorithm implementation in Java for undirected graph doesn't work?

My implementation for directed graph works fine. It's a "lazy" version because it uses simple priority queues instead of indexed ones. I changed the code to get a solution for undirected graphs but it doesn't work. dijkstra(int s) is a method of a class Graph. The implementation of Graph is based on a list of adjacencies. The entire code is based on the explanations of Sedgewick's book.
public void dijkstra(int s) {
marked = new boolean[V];
distTo = new int[V];
edgeTo = new Edge[V];
Comparator<Edge> comparator = new Comparator<Edge>() {
public int compare(Edge e1, Edge e2) {
int dist1 = distTo[e1.either()] + e1.weight();
int dist2 = distTo[e2.either()] + e2.weight();
if (dist1 < dist2) {
return -1;
} else if (dist1 > dist2) {
return 1;
} else {
return 0;
}
}
};
pq = new PriorityQueue<Edge>(comparator);
for (int v = 0; v < V; ++v) {
distTo[v] = Integer.MAX_VALUE;
}
distTo[s] = 0;
relax(s);
while (!pq.isEmpty()) {
Edge e = pq.poll();
int v = e.either();
int w = e.other(v);
if (!marked[w]) {
relax(w);
}
}
}
private void relax(int v) {
marked[v] = true;
for (Edge e : adj[v]) {
int w = e.other(v);
if (distTo[w] > distTo[v] + e.weight()) {
distTo[w] = distTo[v] + e.weight();
edgeTo[w] = e;
pq.add(e);
}
}
}
I solved it. Stupid mistake. Instead of adding the edges
v->w and w->v
I added the edges
v->w and w->w
i.e. I added the same edge twice, without creating the reverse edge.

Java - ArrayList of structure Intersections

I need to call GetNewItem function million times;
Items XY = GetNewItem(X, Y);
Items XYZ = GetNewItem(XY, Z);
Items XZ = GetNewItem(X, Z);
Items YZ = GetNewItem(Y, Z);
This function aims to
1- find intersection between ArrayList of structure namely
ArrayList<Records> RecordLists
2- and it also calculates the probability for the new ArrayList , this is my code:
class Records {
public int RecordId;
public double Prob;
}
class Items {
public ArrayList<Integer> itemId;
public ArrayList<Records> RecordLists;
public double ItemProb = 0.0;
};
private ArrayList<Records> Intersection(ArrayList<Records> list1, ArrayList<Records> list2) {
ArrayList<Records> Result = new ArrayList<>();
int i = 0, j = 0;
while (i < list1.size() && j < list2.size()) {
if (list1.get(i).RecordId== (list2.get(j).RecordId)) {
Records RecordDetails= new Records();
RecordDetails.RecordId= list1.get(i).RecordId;
RecordDetails.Prob+= 1;
Result.add(RecordDetails);
i++;
j++;
} else if (list1.get(i).RecordId < list2.get(j).RecordId) {
i++;
} else if (list1.get(i).RecordId > list2.get(j).RecordId) {
j++;
}
}
return Result;
}
public Items GetNewItem(Items item1, Items item2) {
Items NewItem = new Items ();
ArrayList<Integer> newItemId = new ArrayList<>();
newItemId.addAll(item1.itemId);
newItemId.addAll(item2.itemId);
NewItem.itemId = newItemId;
NewItem.RecordLists= Intersection(item1.RecordLists,item2.RecordLists);
NewItem.ItemProb = getProb(NewItem.RecordLists);
return NewItem ;
}
private double getProb(ArrayList<Records> RProb) {
double IProb = 0.0;
for (int i = 0; i < RProb.size(); i++) {
IProb += RProb.get(i).Prob;
}
return IProb ;
}
For this code I got 'out of memory error'
I don't know how to save the memory and time, I tried this solution:
java.lang.OutOfMemoryError: Java heap space with NetBeans
but my computer did freeze. I don't know what else I have to do.
Please use java conventions, e.g. variables in camel case, non public variables in classes (use getters/constructor/setters)
I'm not sure why are you getting the intersection that way, with that i and j variables.
Please try:
public <T> List<T> intersection(List<T> list1, List<T> list2) {
List<T> list = new ArrayList<T>();
for (T t : list1) {
if(list2.contains(t)) {
list.add(t);
}
}
return list;
}
If you want to calculate something else maybe do it in a separate method?
Use floats instead of doubles.
Could you please paste whole code? I would like to reproduce this.

Java DFS Backtracking in an adjacency matrix

I'm implementing a DFS search to run in an adjacency matrix. With this i want to solve de euler path problem.
I already have DFS running with no problems, but now i want to modify it so it will perform backtrack whenever it tries to visit an edge that already has been visited.
Here's my current code:
public class Graph {
private int numVertex;
private int numEdges;
private boolean[][] adj;
public Graph(int numVertex, int numEdges) {
this.numVertex = numVertex;
this.numEdges = numEdges;
this.adj = new boolean[numVertex+1][numVertex+1];
}
public void addEdge(int start, int end){
adj[start][end] = true;
adj[end][start] = true;
}
List<Integer> visited = new ArrayList<Integer>();
public Integer DFS(Graph G, int startVertex){
int i=0;
pilha.push(startVertex);
for(i=0; i<G.numVertex; i++){
if(G.adj[i][startVertex] != false){
System.out.println("i: " + i);
G.adj[i][startVertex] = false;
G.adj[startVertex][i] = false;
DFS(G, i);
pilha.push(i);
G.adj[i][startVertex] = true;
G.adj[startVertex][i] = true;
}
/* else{
pilha.pop();
}*/
if(!pilha.isEmpty()){
int c = pilha.pop();
visited.add(c);
System.out.println("visited: " + visited);
}
}
return -1;
}
Stack<Integer> pilha = new Stack();
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int numVertices = input.nextInt();
int numLinks = input.nextInt();
int startNode = input.nextInt();
Graph g = new Graph(numVertices, numLinks);
for(int i = 0; i<numLinks; i++){
g.addEdge(input.nextInt(),input.nextInt());
}
g.DFS(g, startNode);
}
}
The problem is, whenever i try to run the pop that is commented, i get an EmptyStackException. Any ideas on how to modify my code so it will backtrack when it tries to visit an edge that already has been visited.
Thx in advance.
That else of yours is getting executed if startvertex is not adjacent to some vertex i.
It really should get that else only if startvertex is not adjacent to any vertex i.
I'd do something like:
bool hasAdjacent = False;
for(i=0; i<G.numVertex; i++){
if(G.adj[i][startVertex] != false){
hasAdjacent = True;
...
}
}
if (!hasAdjacent) {
int c = pilha.pop();
visited.add(c);
}
I'm not giving you a complete solution, but I think this solves your main logic problem.

Checking for odd cycles in an undirected graph

I'm back with another similar question. I am currently working on a Java program that will check if a graph is 2-colorable, i.e. if it contains no odd cycles (cycles of odd number length). The entire algorithm is supposed to run in O(V+E) time (V being all vertices and E being all edges in the graph). My current algorithm does a Depth First Search, recording all vertices in the path it takes, then looks for a back edge, and then records between which vertices the edge is between. Next it traces a path from one end of the back edge until it hits the other vertex on the other end of the edge, thus retracing the cycle that the back edge completes.
I was under the impression that this kind of traversing could be done in O(V+E) time for all cycles that exist in my graph, but I must be missing something, because my algorithm is running for a ridiculously long time for very large graphs (10k nodes, no idea how many edges).
Is my algorithm completely wrong? And if so, can anyone point me in the right direction for a better way to record these cycles or possibly tell if they have odd numbers of vertices? Thanks for any and all help you guys can give. Code is below if you need it.
Addition: Sorry I forgot, if the graph is not 2-colorable, I need to provide an odd cycle that proves that it is not.
package algorithms311;
import java.util.*;
import java.io.*;
public class CS311 {
public static LinkedList[] DFSIter(Vertex[] v) {
LinkedList[] VOandBE = new LinkedList[2];
VOandBE[0] = new LinkedList();
VOandBE[1] = new LinkedList();
Stack stack = new Stack();
stack.push(v[0]);
v[0].setColor("gray");
while(!stack.empty()) {
Vertex u = (Vertex) stack.peek();
LinkedList adjList = u.getAdjList();
VOandBE[0].add(u.getId());
boolean allVisited = true;
for(int i = 0; i < adjList.size(); i++) {
if(v[(Integer)adjList.get(i)].getColor().equals("white")) {
allVisited = false;
break;
}
else if(v[(Integer)adjList.get(i)].getColor().equals("gray") && u.getPrev() != (Integer)adjList.get(i)) {
int[] edge = new int[2]; //pair of vertices
edge[0] = u.getId(); //from u
edge[1] = (Integer)adjList.get(i); //to v
VOandBE[1].add(edge);
}
}
if(allVisited) {
u.setColor("black");
stack.pop();
}
else {
for(int i = 0; i < adjList.size(); i++) {
if(v[(Integer)adjList.get(i)].getColor().equals("white")) {
stack.push(v[(Integer)adjList.get(i)]);
v[(Integer)adjList.get(i)].setColor("gray");
v[(Integer)adjList.get(i)].setPrev(u.getId());
break;
}
}
}
}
return VOandBE;
}
public static void checkForTwoColor(String g) { //input is a graph formatted as assigned
String graph = g;
try {
// --Read First Line of Input File
// --Find Number of Vertices
FileReader file1 = new FileReader("W:\\Documents\\NetBeansProjects\\algorithms311\\src\\algorithms311\\" + graph);
BufferedReader bReaderNumEdges = new BufferedReader(file1);
String numVertS = bReaderNumEdges.readLine();
int numVert = Integer.parseInt(numVertS);
System.out.println(numVert + " vertices");
// --Make Vertices
Vertex vertex[] = new Vertex[numVert];
for(int k = 0; k <= numVert - 1; k++) {
vertex[k] = new Vertex(k);
}
// --Adj Lists
FileReader file2 = new FileReader("W:\\Documents\\NetBeansProjects\\algorithms311\\src\\algorithms311\\" + graph);
BufferedReader bReaderEdges = new BufferedReader(file2);
bReaderEdges.readLine(); //skip first line, that's how many vertices there are
String edge;
while((edge = bReaderEdges.readLine()) != null) {
StringTokenizer ST = new StringTokenizer(edge);
int vArr[] = new int[2];
for(int j = 0; ST.hasMoreTokens(); j++) {
vArr[j] = Integer.parseInt(ST.nextToken());
}
vertex[vArr[0]-1].addAdj(vArr[1]-1);
vertex[vArr[1]-1].addAdj(vArr[0]-1);
}
LinkedList[] l = new LinkedList[2];
l = DFSIter(vertex);//DFS(vertex);
System.out.println(l[0]);
for(int i = 0; i < l[1].size(); i++) {
int[] j = (int[])l[1].get(i);
System.out.print(" [" + j[0] + ", " + j[1] + "] ");
}
LinkedList oddCycle = new LinkedList();
boolean is2Colorable = true;
//System.out.println("iterate through list of back edges");
for(int i = 0; i < l[1].size(); i++) { //iterate through the list of back edges
//System.out.println(i);
int[] q = (int[])(l[1].get(i)); // q = pair of vertices that make up a back edge
int u = q[0]; // edge (u,v)
int v = q[1];
LinkedList cycle = new LinkedList();
if(l[0].indexOf(u) < l[0].indexOf(v)) { //check if u is before v
for(int z = l[0].indexOf(u); z <= l[0].indexOf(v); z++) { //if it is, look for u first; from u to v
cycle.add(l[0].get(z));
}
}
else if(l[0].indexOf(v) < l[0].indexOf(u)) {
for(int z = l[0].indexOf(v); z <= l[0].indexOf(u); z++) { //if it is, look for u first; from u to v
cycle.add(l[0].get(z));
}
}
if((cycle.size() & 1) != 0) { //if it has an odd cycle, print out the cyclic nodes or write them to a file
is2Colorable = false;
oddCycle = cycle;
break;
}
}
if(!is2Colorable) {
System.out.println("Graph is not 2-colorable, odd cycle exists");
if(oddCycle.size() <= 50) {
System.out.println(oddCycle);
}
else {
try {
BufferedWriter outFile = new BufferedWriter(new FileWriter("W:\\Documents\\NetBeansProjects\\algorithms311\\src\\algorithms311\\" + graph + "OddCycle.txt"));
String cyc = oddCycle.toString();
outFile.write(cyc);
outFile.close();
}
catch (IOException e) {
System.out.println("Could not write file");
}
}
}
}
catch (IOException e) {
System.out.println("Could not open file");
}
System.out.println("Done!");
}
public static void main(String[] args) {
//checkForTwoColor("smallgraph1");
//checkForTwoColor("smallgraph2");
//checkForTwoColor("smallgraph3");
//checkForTwoColor("smallgraph4");
checkForTwoColor("smallgraph5");
//checkForTwoColor("largegraph1");
}
}
Vertex class
package algorithms311;
import java.util.*;
public class Vertex implements Comparable {
public int id;
public LinkedList adjVert = new LinkedList();
public String color = "white";
public int dTime;
public int fTime;
public int prev;
public boolean visited = false;
public Vertex(int idnum) {
id = idnum;
}
public int getId() {
return id;
}
public int compareTo(Object obj) {
Vertex vert = (Vertex) obj;
return id-vert.getId();
}
#Override public String toString(){
return "Vertex # " + id;
}
public void setColor(String newColor) {
color = newColor;
}
public String getColor() {
return color;
}
public void setDTime(int d) {
dTime = d;
}
public void setFTime(int f) {
fTime = f;
}
public int getDTime() {
return dTime;
}
public int getFTime() {
return fTime;
}
public void setPrev(int v) {
prev = v;
}
public int getPrev() {
return prev;
}
public LinkedList getAdjList() {
return adjVert;
}
public void addAdj(int a) { //adds a vertex id to this vertex's adj list
adjVert.add(a);
}
public void visited() {
visited = true;
}
public boolean wasVisited() {
return visited;
}
}
I was under the impression that this kind of traversing could be done in O(V+E) time for all cycles that exist in my graph
There may be much more cycles than O(V+E) in a graph. If you iterate all of them, you will run long.
Back to your original idea, you could just try to implement a straightforward algorithm to color graph in two colors (mark an arbitrary node as black, all neighbors in white, all their neighbors in black, etc; that would be a breadth-first search). That is indeed done in O(V+E) time. If you succeed, then graph is 2-colorable. If you fail, it's not.
Edit: If you need a cycle that proves graph is not 2-colorable, just record for each node the vertex you traversed into it from. When you happen to traverse from black vertex A to black vertex B (thus needing to color black B into white and proving your graph is not 2-colorable), you get the cycle by looking back to parents:
X -> Y -> Z -> U -> V -> P -> Q -> A
\-> D -> E -> B
Then, A-B-E-D-V-P-Q (the paths up to their common ancestor) is the cycle you needed.
Note that in this version you don't have to check all cycles, you just output a first cycle, where back-edge in the tree has both vertexes colored in the same color.
you are describing a bipartite graph. a bipartite graph is 2 colorable and it contains no odd length cycles. You can use BFS to prove that a graph is bipartite or not. Hope this helps.

Categories