import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;
public class Graph {
private int numV; // # of vertices
private boolean isdirected; // is it a directed graph?
private List<Edge>[] edges;
public Graph(int numV, boolean isdirected) {
this.numV = numV;
this.isdirected = isdirected;
edges = new List[numV];
for (int i = 0; i < numV; i++) {
edges[i] = new LinkedList<Edge>();
}
}
public int getNumV() { // Returns the # of vertices
return numV;
}
public boolean isDirected() { // Is this a directed graph?
return isdirected;
}
public boolean isEmpty() {
return numV == 0;
}
public void clear() {
numV = 0;
isdirected = false;
edges = null;
}
void insert(Edge edge) { // Insert a new edge into the graph
edges[edge.getSource()].add(edge);
if (!isDirected()) {
edges[edge.getDest()].add(new Edge(edge.getDest(),
edge.getSource(), edge.getWeight()));
}
}
boolean isEdge(int source, int dest) { // Is there an edge <source, dest>?
return edges[source].contains(new Edge(source, dest));
}
public void dfTraversal() {
boolean[] visited = new boolean[numV];
for (int i = 0; i < visited.length; i++) {
visited[i] = false;
}
for (int i = 0; i < numV; i++) {
if (!visited[i])
dft(i, visited);
}
}
private void dft(int v, boolean[] visited) {
System.out.println(v); // visit the node
visited[v] = true;
for (Edge e : edges[v]) {
int w = e.getDest();
if (!visited[w])
dft(w, visited);
}
}
public void depthFirst() {
Stack<Integer> queue = new Stack<Integer>();
boolean[] visited = new boolean[numV];
for (int i = 0; i < visited.length; i++)
visited[i] = false;
for (int i = 0; i < numV; i++) {
if (!visited[i]) {
queue.push(i);
while (!queue.isEmpty()) {
int u = queue.pop();
visited[u] = true;
System.out.println(u);
for (Edge e : edges[u]) {
int w = e.getDest();
if (!visited[w]) {
queue.push(w);
}
}
}
}
}
}
public void bfTraversal() {
Queue<Integer> queue = new LinkedList<Integer>();
boolean[] visited = new boolean[numV];
for (int i = 0; i < visited.length; i++)
visited[i] = false;
for (int i = 0; i < numV; i++) {
if (!visited[i]) {
queue.add(i);
visited[i] = true;
System.out.println(i);
}
while (!queue.isEmpty()) {
int u = queue.remove();
for (Edge e : edges[u]) {
int w = e.getDest();
if (!visited[w]) {
queue.add(w);
visited[w] = true;
System.out.println(w);
}
}
}
}
}
public void readGraph(Scanner scan) {
String line;
while (scan.hasNextLine()) {
line = scan.nextLine();
String[] tokens = line.split("\\s+");
int source = Integer.parseInt(tokens[0]);
int dest = Integer.parseInt(tokens[1]);
double weight = 1.0;
if (tokens.length == 3) {
weight = Double.parseDouble(tokens[2]);
}
insert(new Edge(source, dest, weight));
}
}
public String toString() {
// print out the vertices
String G = (isdirected ? "Directed ": "Undirected ") + "Graph:\nVertices: <";
for (int i = 0; i < edges.length - 1; i++) {
G += i + ", ";
}
G += edges.length - 1 + ">\n";
// print out the edges
G += "Edges:\n";
for (int i = 0; i < numV; i++) {
for (int j = 0; j < edges[i].size(); j++) {
G += edges[i].get(j) + "\n";
}
}
return G;
}
}