diff --git a/algs4/algs4.csproj b/algs4/algs4.csproj
index 08f4e16..a5f7289 100644
--- a/algs4/algs4.csproj
+++ b/algs4/algs4.csproj
@@ -54,10 +54,13 @@
+
+
+
diff --git a/algs4/algs4/DigraphGenerator.cs b/algs4/algs4/DigraphGenerator.cs
new file mode 100644
index 0000000..ffd1527
--- /dev/null
+++ b/algs4/algs4/DigraphGenerator.cs
@@ -0,0 +1,528 @@
+using System;
+using algs4.stdlib;
+
+namespace algs4.algs4
+{
+ public static class DigraphGenerator
+ {
+ private class Edge : IComparable
+ {
+ private readonly int _v;
+ private readonly int _w;
+
+ public Edge(int v, int w)
+ {
+ _v = v;
+ _w = w;
+ }
+ public int CompareTo(Edge that)
+ {
+ if (_v < that._v)
+ {
+ return -1;
+ }
+ if (_v > that._v)
+ {
+ return +1;
+ }
+ if (_w < that._w)
+ {
+ return -1;
+ }
+ if (_w > that._w)
+ {
+ return +1;
+ }
+ return 0;
+ }
+ }
+
+ ///
+ /// Returns a random simple digraph containing V vertices and E edges.
+ ///
+ /// the number of vertices
+ /// the number of vertices
+ /// a random simple digraph on V vertices, containing a total of E edges
+ public static Digraph Simple(int v, int e)
+ {
+ if (e > (long)v * (v - 1))
+ {
+ throw new ArgumentException("Too many edges");
+ }
+ if (e < 0)
+ {
+ throw new ArgumentException("Too few edges");
+ }
+ Digraph g = new Digraph(v);
+ Set set = new Set();
+ while (g.E() < e)
+ {
+ int vCount = StdRandom.Uniform(v);
+ int wCount = StdRandom.Uniform(v);
+ Edge edge = new Edge(vCount, wCount);
+ if ((vCount != wCount) && !set.Contains(edge))
+ {
+ set.Add(edge);
+ g.AddEdge(vCount, wCount);
+ }
+ }
+ return g;
+ }
+
+ ///
+ /// Returns a random simple digraph on V vertices, with an
+ /// edge between any two vertices with probability p. This is sometimes
+ /// referred to as the Erdos-Renyi random digraph model.
+ /// This implementations takes time propotional to V^2 (even if p is small).
+ ///
+ /// the number of vertices
+ /// the probability of choosing an edge
+ /// a random simple digraph on V vertices, with an edge between any two vertices with probability p
+ public static Digraph Simple(int v, double p)
+ {
+ if (p < 0.0 || p > 1.0)
+ {
+ throw new ArgumentException("Probability must be between 0 and 1");
+ }
+ Digraph g = new Digraph(v);
+ for (int vertex = 0; vertex < v; vertex++)
+ {
+ for (int w = 0; w < v; w++)
+ {
+ if (vertex != w)
+ {
+ if (StdRandom.Bernoulli(p))
+ {
+ g.AddEdge(vertex, w);
+ }
+ }
+ }
+ }
+ return g;
+ }
+
+ ///
+ /// Returns the complete digraph on V vertices.
+ ///
+ /// the number of vertices
+ /// the complete digraph on V vertices
+ public static Digraph Complete(int v)
+ {
+ return Simple(v, v * (v - 1));
+ }
+
+ ///
+ /// Returns a random simple DAG containing V vertices and E edges.
+ /// Note: it is not uniformly selected at random among all such DAGs.
+ ///
+ /// the number of vertices
+ /// the number of vertices
+ /// a random simple DAG on V vertices, containing a total of E edges
+ public static Digraph DAG(int v, int e)
+ {
+ if (e > (long)v * (v - 1) / 2)
+ {
+ throw new ArgumentException("Too many edges");
+ }
+ if (e < 0)
+ {
+ throw new ArgumentException("Too few edges");
+ }
+ Digraph g = new Digraph(v);
+ Set set = new Set();
+ int[] vertices = new int[v];
+ for (int i = 0; i < v; i++)
+ {
+ vertices[i] = i;
+ }
+ StdRandom.Shuffle(vertices);
+ while (g.E() < e)
+ {
+ int vCount = StdRandom.Uniform(v);
+ int wCount = StdRandom.Uniform(v);
+ Edge edge = new Edge(vCount, wCount);
+ if ((vCount < wCount) && !set.Contains(edge))
+ {
+ set.Add(edge);
+ g.AddEdge(vertices[vCount], vertices[wCount]);
+ }
+ }
+ return g;
+ }
+
+ ///
+ /// Returns a random tournament digraph on V vertices. A tournament digraph
+ /// is a DAG in which for every two vertices, there is one directed edge.
+ /// A tournament is an oriented complete graph.
+ ///
+ /// the number of vertices
+ /// a random tournament digraph on V vertices
+ public static Digraph Tournament(int v)
+ {
+ Digraph g = new Digraph(v);
+ for (int vertex = 0; vertex < g.V(); vertex++)
+ {
+ for (int w = vertex + 1; w < g.V(); w++)
+ {
+ if (StdRandom.Bernoulli(0.5))
+ {
+ g.AddEdge(vertex, w);
+ }
+ else
+ {
+ g.AddEdge(w, vertex);
+ }
+ }
+ }
+ return g;
+ }
+
+ ///
+ /// Returns a random rooted-in DAG on V vertices and E edges.
+ /// A rooted in-tree is a DAG in which there is a single vertex
+ /// reachable from every other vertex.
+ /// The DAG returned is not chosen uniformly at random among all such DAGs.
+ ///
+ /// the number of vertices
+ /// the number of edges
+ /// a random rooted-in DAG on V vertices and E edges
+ public static Digraph RootedInDAG(int v, int e)
+ {
+ if (e > (long)v * (v - 1) / 2)
+ {
+ throw new ArgumentException("Too many edges");
+ }
+ if (e < v - 1)
+ {
+ throw new ArgumentException("Too few edges");
+ }
+ Digraph g = new Digraph(v);
+ Set set = new Set();
+
+ // fix a topological order
+ int[] vertices = new int[v];
+ for (int i = 0; i < v; i++)
+ {
+ vertices[i] = i;
+ }
+ StdRandom.Shuffle(vertices);
+
+ // one edge pointing from each vertex, other than the root = vertices[V-1]
+ for (int vertex = 0; vertex < v - 1; vertex++)
+ {
+ int w = StdRandom.Uniform(vertex + 1, v);
+ Edge edge = new Edge(vertex, w);
+ set.Add(edge);
+ g.AddEdge(vertices[vertex], vertices[w]);
+ }
+
+ while (g.E() < e)
+ {
+ int vCount = StdRandom.Uniform(v);
+ int wCount = StdRandom.Uniform(v);
+ Edge edge = new Edge(vCount, wCount);
+ if ((vCount < wCount) && !set.Contains(edge))
+ {
+ set.Add(edge);
+ g.AddEdge(vertices[vCount], vertices[wCount]);
+ }
+ }
+ return g;
+ }
+
+ ///
+ /// Returns a random rooted-out DAG on V vertices and E edges.
+ /// A rooted out-tree is a DAG in which every vertex is reachable from a
+ /// single vertex.
+ /// The DAG returned is not chosen uniformly at random among all such DAGs.
+ ///
+ /// the number of vertices
+ /// the number of edges
+ /// a random rooted-out DAG on V vertices and E edges
+ public static Digraph RootedOutDAG(int v, int e)
+ {
+ if (e > (long)v * (v - 1) / 2)
+ {
+ throw new ArgumentException("Too many edges");
+ }
+ if (e < v - 1)
+ {
+ throw new ArgumentException("Too few edges");
+ }
+ Digraph g = new Digraph(v);
+ Set set = new Set();
+
+ // fix a topological order
+ int[] vertices = new int[v];
+ for (int i = 0; i < v; i++)
+ {
+ vertices[i] = i;
+ }
+ StdRandom.Shuffle(vertices);
+
+ // one edge pointing from each vertex, other than the root = vertices[V-1]
+ for (int vertex = 0; vertex < v - 1; vertex++)
+ {
+ int wCount = StdRandom.Uniform(vertex + 1, v);
+ Edge edge = new Edge(wCount, vertex);
+ set.Add(edge);
+ g.AddEdge(vertices[wCount], vertices[vertex]);
+ }
+
+ while (g.E() < e)
+ {
+ int vCount = StdRandom.Uniform(v);
+ int wCount = StdRandom.Uniform(v);
+ Edge edge = new Edge(wCount, vCount);
+ if ((vCount < wCount) && !set.Contains(edge))
+ {
+ set.Add(edge);
+ g.AddEdge(vertices[wCount], vertices[vCount]);
+ }
+ }
+ return g;
+ }
+
+ ///
+ /// Returns a random rooted-in tree on V vertices.
+ /// A rooted in-tree is an oriented tree in which there is a single vertex
+ /// reachable from every other vertex.
+ /// The tree returned is not chosen uniformly at random among all such trees.
+ ///
+ /// the number of vertices
+ /// a random rooted-in tree on V vertices
+ public static Digraph RootedInTree(int v)
+ {
+ return RootedInDAG(v, v - 1);
+ }
+
+ ///
+ /// Returns a random rooted-out tree on V vertices. A rooted out-tree
+ /// is an oriented tree in which each vertex is reachable from a single vertex.
+ /// It is also known as a arborescence or branching.
+ /// The tree returned is not chosen uniformly at random among all such trees.
+ ///
+ /// the number of vertices
+ /// a random rooted-out tree on V vertices
+ public static Digraph RootedOutTree(int v)
+ {
+ return RootedOutDAG(v, v - 1);
+ }
+
+ ///
+ /// Returns a path digraph on V vertices.
+ ///
+ /// the number of vertices in the path
+ /// a digraph that is a directed path on V vertices
+ public static Digraph Path(int v)
+ {
+ Digraph g = new Digraph(v);
+ int[] vertices = new int[v];
+ for (int i = 0; i < v; i++)
+ {
+ vertices[i] = i;
+ }
+ StdRandom.Shuffle(vertices);
+ for (int i = 0; i < v - 1; i++)
+ {
+ g.AddEdge(vertices[i], vertices[i + 1]);
+ }
+ return g;
+ }
+
+ ///
+ /// Returns a complete binary tree digraph on V vertices.
+ ///
+ /// the number of vertices in the binary tree
+ /// a digraph that is a complete binary tree on V vertices
+ public static Digraph BinaryTree(int v)
+ {
+ Digraph g = new Digraph(v);
+ int[] vertices = new int[v];
+ for (int i = 0; i < v; i++) vertices[i] = i;
+ StdRandom.Shuffle(vertices);
+ for (int i = 1; i < v; i++)
+ {
+ g.AddEdge(vertices[i], vertices[(i - 1) / 2]);
+ }
+ return g;
+ }
+
+ ///
+ /// Returns a cycle digraph on V vertices.
+ ///
+ /// the number of vertices in the cycle
+ /// a digraph that is a directed cycle on v vertices
+ public static Digraph Cycle(int v)
+ {
+ Digraph g = new Digraph(v);
+ int[] vertices = new int[v];
+ for (int i = 0; i < v; i++)
+ {
+ vertices[i] = i;
+ }
+ StdRandom.Shuffle(vertices);
+ for (int i = 0; i < v - 1; i++)
+ {
+ g.AddEdge(vertices[i], vertices[i + 1]);
+ }
+ g.AddEdge(vertices[v - 1], vertices[0]);
+ return g;
+ }
+
+ ///
+ /// Returns a random simple digraph on V vertices, E
+ /// edges and (at least) c strong components. The vertices are randomly
+ /// assigned int labels between 0 and c-1 (corresponding to
+ /// strong components). Then, a strong component is creates among the vertices
+ /// with the same label. Next, random edges (either between two vertices with
+ /// the same labels or from a vetex with a smaller label to a vertex with a
+ /// larger label). The number of components will be equal to the number of
+ /// distinct labels that are assigned to vertices.
+ ///
+ /// the number of vertices
+ /// the number of edges
+ /// the (maximum) number of strong components
+ /// a random simple digraph on V vertices and E edges, with (at most) c strong components
+ public static Digraph Strong(int v, int e, int c)
+ {
+ if (c >= v || c <= 0)
+ {
+ throw new ArgumentException("Number of components must be between 1 and V");
+ }
+ if (e <= 2 * (v - c))
+ {
+ throw new ArgumentException("Number of edges must be at least 2(V-c)");
+ }
+ if (e > (long)v * (v - 1) / 2)
+ {
+ throw new ArgumentException("Too many edges");
+ }
+
+ // the digraph
+ Digraph g = new Digraph(v);
+
+ // edges.Added to G (to avoid duplicate edges)
+ Set set = new Set();
+
+ int[] label = new int[v];
+ for (int vertex = 0; vertex < v; vertex++)
+ {
+ label[vertex] = StdRandom.Uniform(c);
+ }
+
+ // make all vertices with label c a strong component by
+ // combining a rooted in-tree and a rooted out-tree
+ for (int i = 0; i < c; i++)
+ {
+ // how many vertices in component c
+ int count = 0;
+ for (int vertex = 0; vertex < g.V(); vertex++)
+ {
+ if (label[vertex] == i)
+ {
+ count++;
+ }
+ }
+
+ // if (count == 0) System.err.println("less than desired number of strong components");
+
+ int[] vertices = new int[count];
+ int j = 0;
+ for (int vertex = 0; vertex < v; vertex++)
+ {
+ if (label[vertex] == i)
+ {
+ vertices[j++] = vertex;
+ }
+ }
+ StdRandom.Shuffle(vertices);
+
+ // rooted-in tree with root = vertices[count-1]
+ for (int vertex = 0; vertex < count - 1; vertex++)
+ {
+ int w = StdRandom.Uniform(vertex + 1, count);
+ Edge edge = new Edge(w, vertex);
+ set.Add(edge);
+ g.AddEdge(vertices[w], vertices[vertex]);
+ }
+
+ // rooted-out tree with root = vertices[count-1]
+ for (int vertex = 0; vertex < count - 1; vertex++)
+ {
+ int w = StdRandom.Uniform(vertex + 1, count);
+ Edge edge = new Edge(vertex, w);
+ set.Add(edge);
+ g.AddEdge(vertices[vertex], vertices[w]);
+ }
+ }
+
+ while (g.E() < e)
+ {
+ int vCount = StdRandom.Uniform(v);
+ int wCount = StdRandom.Uniform(v);
+ Edge edge = new Edge(vCount, wCount);
+ if (!set.Contains(edge) && vCount != wCount && label[vCount] <= label[wCount])
+ {
+ set.Add(edge);
+ g.AddEdge(vCount, wCount);
+ }
+ }
+
+ return g;
+ }
+
+ ///
+ /// Unit tests the DigraphGenerator library.
+ ///
+ ///
+ public static void RunMain(string[] args)
+ {
+ int v = int.Parse(args[0]);
+ int e = int.Parse(args[1]);
+ Console.WriteLine("complete graph");
+ Console.WriteLine(Complete(v));
+ Console.WriteLine();
+
+ Console.WriteLine("simple");
+ Console.WriteLine(Simple(v, e));
+ Console.WriteLine();
+
+ Console.WriteLine("path");
+ Console.WriteLine(Path(v));
+ Console.WriteLine();
+
+ Console.WriteLine("cycle");
+ Console.WriteLine(Cycle(v));
+ Console.WriteLine();
+
+ Console.WriteLine("binary tree");
+ Console.WriteLine(BinaryTree(v));
+ Console.WriteLine();
+
+ Console.WriteLine("tournament");
+ Console.WriteLine(Tournament(v));
+ Console.WriteLine();
+
+ Console.WriteLine("DAG");
+ Console.WriteLine(DAG(v, e));
+ Console.WriteLine();
+
+ Console.WriteLine("rooted-in DAG");
+ Console.WriteLine(RootedInDAG(v, e));
+ Console.WriteLine();
+
+ Console.WriteLine("rooted-out DAG");
+ Console.WriteLine(RootedOutDAG(v, e));
+ Console.WriteLine();
+
+ Console.WriteLine("rooted-in tree");
+ Console.WriteLine(RootedInTree(v));
+ Console.WriteLine();
+
+ Console.WriteLine("rooted-out DAG");
+ Console.WriteLine(RootedOutTree(v));
+ Console.WriteLine();
+ }
+ }
+}
diff --git a/algs4/algs4/Graph.cs b/algs4/algs4/Graph.cs
new file mode 100644
index 0000000..c232f8f
--- /dev/null
+++ b/algs4/algs4/Graph.cs
@@ -0,0 +1,179 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using algs4.stdlib;
+
+namespace algs4.algs4
+{
+ public class Graph
+ {
+ private readonly int _v;
+ private int _e;
+ private readonly Bag[] _adj;
+
+ ///
+ /// Initializes an empty graph with V vertices and 0 edges.
+ ///
+ /// the number of vertices
+ public Graph(int v)
+ {
+ if (v < 0)
+ {
+ throw new ArgumentException("Number of vertices must be nonnegative");
+ }
+ _v = v;
+ _e = 0;
+ _adj = new Bag[v];
+ for (int vertex = 0; vertex < v; vertex++)
+ {
+ _adj[vertex] = new Bag();
+ }
+ }
+
+ ///
+ /// Initializes a graph from an input stream.
+ /// The format is the number of vertices V,
+ /// followed by the number of edges E,
+ /// followed by E pairs of vertices, with each entry separated by whitespace.
+ ///
+ /// the input stream
+ public Graph(In input)
+ : this(input.ReadInt())
+ {
+
+ int e = input.ReadInt();
+ if (e < 0)
+ {
+ throw new ArgumentException("Number of edges must be nonnegative");
+ }
+ for (int i = 0; i < e; i++)
+ {
+ int v = input.ReadInt();
+ int w = input.ReadInt();
+ AddEdge(v, w);
+ }
+ }
+
+ ///
+ /// Initializes a new graph that is a deep copy of G.
+ ///
+ /// the graph to copy
+ public Graph(Graph g)
+ : this(g.V())
+ {
+ _e = g.E();
+ for (int v = 0; v < g.V(); v++)
+ {
+ // reverse so that adjacency list is in same order as original
+ Stack reverse = new Stack();
+ foreach (int w in g._adj[v])
+ {
+ reverse.Push(w);
+ }
+ foreach (int w in reverse)
+ {
+ _adj[v].Add(w);
+ }
+ }
+ }
+
+ ///
+ /// Returns the number of vertices in the graph.
+ ///
+ /// the number of vertices in the graph
+ public int V()
+ {
+ return _v;
+ }
+
+ ///
+ /// Returns the number of edges in the graph.
+ ///
+ /// the number of edges in the graph
+ public int E()
+ {
+ return _e;
+ }
+
+ ///
+ /// Throw an IndexOutOfBoundsException unless 0 <= v < _v
+ ///
+ ///
+ private void ValidateVertex(int v)
+ {
+ if (v < 0 || v >= _v)
+ {
+ throw new IndexOutOfRangeException("vertex " + v + " is not between 0 and " + (_v - 1));
+ }
+ }
+
+ ///
+ /// Adds the undirected edge v-w to the graph.
+ ///
+ /// one vertex in the edge
+ /// the other vertex in the edge
+ public void AddEdge(int v, int w)
+ {
+ ValidateVertex(v);
+ ValidateVertex(w);
+ _e++;
+ _adj[v].Add(w);
+ _adj[w].Add(v);
+ }
+
+ ///
+ /// Returns the vertices adjacent to vertex v.
+ ///
+ /// the vertex
+ /// the vertices adjacent to vertex v as an Iterable
+ public IEnumerable Adj(int v)
+ {
+ ValidateVertex(v);
+ return _adj[v];
+ }
+
+ ///
+ /// Returns the degree of vertex v.
+ ///
+ /// the vertex
+ /// the degree of vertex v
+ public int Degree(int v)
+ {
+ ValidateVertex(v);
+ return _adj[v].Size();
+ }
+
+ ///
+ /// Returns a string representation of the graph.
+ /// This method takes time proportional to E + V.
+ ///
+ /// the number of vertices V, followed by the number of edges E, followed by the V adjacency lists
+ public override string ToString()
+ {
+ StringBuilder s = new StringBuilder();
+ string newline = Environment.NewLine;
+ s.Append(_v + " vertices, " + _e + " edges " + newline);
+ for (int v = 0; v < _v; v++)
+ {
+ s.Append(v + ": ");
+ foreach (int w in _adj[v])
+ {
+ s.Append(w + " ");
+ }
+ s.Append(newline);
+ }
+ return s.ToString();
+ }
+
+ ///
+ /// Unit tests the Graph data type.
+ ///
+ ///
+ public static void RunMain(string[] args)
+ {
+ In input = new In(args[0]);
+ Graph g = new Graph(input);
+ StdOut.PrintLn(g);
+ }
+ }
+}
diff --git a/algs4/algs4/GraphGenerator.cs b/algs4/algs4/GraphGenerator.cs
new file mode 100644
index 0000000..c1f6f06
--- /dev/null
+++ b/algs4/algs4/GraphGenerator.cs
@@ -0,0 +1,496 @@
+using System;
+using algs4.stdlib;
+
+namespace algs4.algs4
+{
+ public class GraphGenerator
+ {
+ private class Edge : IComparable
+ {
+ private readonly int _v;
+ private readonly int _w;
+
+ public Edge(int v, int w)
+ {
+ if (v < w)
+ {
+ _v = v;
+ _w = w;
+ }
+ else
+ {
+ _v = w;
+ _w = v;
+ }
+ }
+
+ public int CompareTo(Edge that)
+ {
+ if (_v < that._v)
+ {
+ return -1;
+ }
+ if (_v > that._v)
+ {
+ return +1;
+ }
+ if (_w < that._w)
+ {
+ return -1;
+ }
+ if (_w > that._w)
+ {
+ return +1;
+ }
+ return 0;
+ }
+ }
+
+ ///
+ /// Returns a random simple graph containing V vertices and E edges.
+ ///
+ /// the number of vertices
+ /// the number of edges
+ /// a random simple graph on V vertices, containing a total of E edges
+ public static Graph Simple(int v, int e)
+ {
+ if (e > (long)v * (v - 1) / 2)
+ {
+ throw new ArgumentException("Too many edges");
+ }
+ if (e < 0)
+ {
+ throw new ArgumentException("Too few edges");
+ }
+ Graph g = new Graph(v);
+ Set set = new Set();
+ while (g.E() < e)
+ {
+ int vCount = StdRandom.Uniform(v);
+ int wCount = StdRandom.Uniform(v);
+ Edge edge = new Edge(vCount, wCount);
+ if ((vCount != wCount) && !set.Contains(edge))
+ {
+ set.Add(edge);
+ g.AddEdge(vCount, wCount);
+ }
+ }
+ return g;
+ }
+
+ ///
+ /// Returns a random simple graph on V vertices, with an
+ /// edge between any two vertices with probability p. This is sometimes
+ /// referred to as the Erdos-Renyi random graph model.
+ ///
+ /// the number of vertices
+ /// the probability of choosing an edge
+ /// a random simple graph on V vertices, with an edge between any two vertices with probability p
+ public static Graph Simple(int v, double p)
+ {
+ if (p < 0.0 || p > 1.0)
+ {
+ throw new ArgumentException("Probability must be between 0 and 1");
+ }
+ Graph g = new Graph(v);
+ for (int vertex = 0; vertex < v; vertex++)
+ {
+ for (int w = vertex + 1; w < v; w++)
+ {
+ if (StdRandom.Bernoulli(p))
+ {
+ g.AddEdge(vertex, w);
+ }
+ }
+ }
+ return g;
+ }
+
+ ///
+ /// Returns the complete graph on V vertices.
+ ///
+ /// the number of vertices
+ /// the complete graph on V vertices
+ public static Graph Complete(int v)
+ {
+ return Simple(v, 1.0);
+ }
+
+ ///
+ /// Returns a complete bipartite graph on V1 and V2 vertices.
+ ///
+ /// the number of vertices in one partition
+ /// the number of vertices in the other partition
+ /// a complete bipartite graph on V1 and V2 vertices
+ public static Graph CompleteBipartite(int v1, int v2)
+ {
+ return Bipartite(v1, v2, v1 * v2);
+ }
+
+ ///
+ /// Returns a random simple bipartite graph on V1 and V2 vertices
+ /// with E edges.
+ ///
+ /// the number of vertices in one partition
+ /// the number of vertices in the other partition
+ /// the number of edges
+ /// a random simple bipartite graph on V1 and V2 vertices, containing a total of E edges
+ public static Graph Bipartite(int v1, int v2, int e)
+ {
+ if (e > (long)v1 * v2)
+ {
+ throw new ArgumentException("Too many edges");
+ }
+ if (e < 0)
+ {
+ throw new ArgumentException("Too few edges");
+ }
+ Graph g = new Graph(v1 + v2);
+
+ int[] vertices = new int[v1 + v2];
+ for (int i = 0; i < v1 + v2; i++)
+ {
+ vertices[i] = i;
+ }
+ StdRandom.Shuffle(vertices);
+
+ Set set = new Set();
+ while (g.E() < e)
+ {
+ int i = StdRandom.Uniform(v1);
+ int j = v1 + StdRandom.Uniform(v2);
+ Edge edge = new Edge(vertices[i], vertices[j]);
+ if (!set.Contains(edge))
+ {
+ set.Add(edge);
+ g.AddEdge(vertices[i], vertices[j]);
+ }
+ }
+ return g;
+ }
+
+ ///
+ /// Returns a random simple bipartite graph on V1 and V2 vertices,
+ /// containing each possible edge with probability p.
+ ///
+ /// the number of vertices in one partition
+ /// the number of vertices in the other partition
+ /// the probability that the graph contains an edge with one endpoint in either side
+ /// a random simple bipartite graph on V1 and V2 vertices, containing each possible edge with probability p
+ public static Graph Bipartite(int v1, int v2, double p)
+ {
+ if (p < 0.0 || p > 1.0)
+ {
+ throw new ArgumentException("Probability must be between 0 and 1");
+ }
+ int[] vertices = new int[v1 + v2];
+ for (int i = 0; i < v1 + v2; i++)
+ {
+ vertices[i] = i;
+ }
+ StdRandom.Shuffle(vertices);
+ Graph g = new Graph(v1 + v2);
+ for (int i = 0; i < v1; i++)
+ {
+ for (int j = 0; j < v2; j++)
+ {
+ if (StdRandom.Bernoulli(p))
+ {
+ g.AddEdge(vertices[i], vertices[v1 + j]);
+ }
+ }
+ }
+ return g;
+ }
+
+ ///
+ /// Returns a path graph on V vertices.
+ ///
+ /// the number of vertices in the path
+ /// a path graph on V vertices
+ public static Graph Path(int v)
+ {
+ Graph g = new Graph(v);
+ int[] vertices = new int[v];
+ for (int i = 0; i < v; i++)
+ {
+ vertices[i] = i;
+ }
+ StdRandom.Shuffle(vertices);
+ for (int i = 0; i < v - 1; i++)
+ {
+ g.AddEdge(vertices[i], vertices[i + 1]);
+ }
+ return g;
+ }
+
+ ///
+ /// Returns a complete binary tree graph on V vertices.
+ ///
+ /// the number of vertices in the binary tree
+ /// a complete binary tree graph on V vertices
+ public static Graph BinaryTree(int v)
+ {
+ Graph g = new Graph(v);
+ int[] vertices = new int[v];
+ for (int i = 0; i < v; i++)
+ {
+ vertices[i] = i;
+ }
+ StdRandom.Shuffle(vertices);
+ for (int i = 1; i < v; i++)
+ {
+ g.AddEdge(vertices[i], vertices[(i - 1) / 2]);
+ }
+ return g;
+ }
+
+ ///
+ /// Returns a cycle graph on V vertices.
+ ///
+ /// the number of vertices in the cycle
+ /// a cycle graph on V vertices
+ public static Graph Cycle(int v)
+ {
+ Graph g = new Graph(v);
+ int[] vertices = new int[v];
+ for (int i = 0; i < v; i++)
+ {
+ vertices[i] = i;
+ }
+ StdRandom.Shuffle(vertices);
+ for (int i = 0; i < v - 1; i++)
+ {
+ g.AddEdge(vertices[i], vertices[i + 1]);
+ }
+ g.AddEdge(vertices[v - 1], vertices[0]);
+ return g;
+ }
+
+ ///
+ /// Returns a wheel graph on V vertices.
+ ///
+ /// the number of vertices in the wheel
+ /// a wheel graph on V vertices: a single vertex connected to every vertex in a cycle on V-1 vertices
+ public static Graph Wheel(int v)
+ {
+ if (v <= 1)
+ {
+ throw new ArgumentException("Number of vertices must be at least 2");
+ }
+ Graph g = new Graph(v);
+ int[] vertices = new int[v];
+ for (int i = 0; i < v; i++)
+ {
+ vertices[i] = i;
+ }
+ StdRandom.Shuffle(vertices);
+
+ // simple cycle on V-1 vertices
+ for (int i = 1; i < v - 1; i++)
+ {
+ g.AddEdge(vertices[i], vertices[i + 1]);
+ }
+ g.AddEdge(vertices[v - 1], vertices[1]);
+
+ // connect vertices[0] to every vertex on cycle
+ for (int i = 1; i < v; i++)
+ {
+ g.AddEdge(vertices[0], vertices[i]);
+ }
+
+ return g;
+ }
+
+ ///
+ /// Returns a star graph on V vertices.
+ ///
+ /// the number of vertices in the star
+ /// a star graph on V vertices: a single vertex connected to every other vertex
+ public static Graph Star(int v)
+ {
+ if (v <= 0)
+ {
+ throw new ArgumentException("Number of vertices must be at least 1");
+ }
+ Graph g = new Graph(v);
+ int[] vertices = new int[v];
+ for (int i = 0; i < v; i++)
+ {
+ vertices[i] = i;
+ }
+ StdRandom.Shuffle(vertices);
+
+ // connect vertices[0] to every other vertex
+ for (int i = 1; i < v; i++)
+ {
+ g.AddEdge(vertices[0], vertices[i]);
+ }
+
+ return g;
+ }
+
+ ///
+ /// Returns a uniformly random k-regular graph on V vertices
+ /// (not necessarily simple). The graph is simple with probability only about e^(-k^2/4),
+ /// which is tiny when k = 14.
+ ///
+ /// the number of vertices in the graph
+ ///
+ /// a uniformly random k-regular graph on V vertices.
+ public static Graph Regular(int v, int k)
+ {
+ if (v * k % 2 != 0)
+ {
+ throw new ArgumentException("Number of vertices * k must be even");
+ }
+ Graph g = new Graph(v);
+
+ // create k copies of each vertex
+ int[] vertices = new int[v * k];
+ for (int vertex = 0; vertex < v; vertex++)
+ {
+ for (int j = 0; j < k; j++)
+ {
+ vertices[vertex + v * j] = vertex;
+ }
+ }
+
+ // pick a random perfect matching
+ StdRandom.Shuffle(vertices);
+ for (int i = 0; i < v * k / 2; i++)
+ {
+ g.AddEdge(vertices[2 * i], vertices[2 * i + 1]);
+ }
+ return g;
+ }
+
+ ///
+ /// Returns a uniformly random tree on V vertices.
+ /// This algorithm uses a Prufer sequence and takes time proportional to V log V.
+ /// http://www.proofwiki.org/wiki/Labeled_Tree_from_Prüfer_Sequence
+ /// http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.36.6484&rep=rep1&type=pdf
+ ///
+ /// the number of vertices in the tree
+ /// a uniformly random tree on V vertices
+ public static Graph Tree(int v)
+ {
+ Graph g = new Graph(v);
+
+ // special case
+ if (v == 1)
+ {
+ return g;
+ }
+
+ // Cayley's theorem: there are V^(V-2) labeled trees on V vertices
+ // Prufer sequence: sequence of V-2 values between 0 and V-1
+ // Prufer's proof of Cayley's theorem: Prufer sequences are in 1-1
+ // with labeled trees on V vertices
+ int[] prufer = new int[v - 2];
+ for (int i = 0; i < v - 2; i++)
+ {
+ prufer[i] = StdRandom.Uniform(v);
+ }
+
+ // degree of vertex v = 1 + number of times it appers in Prufer sequence
+ int[] degree = new int[v];
+ for (int vertex = 0; vertex < v; vertex++)
+ {
+ degree[vertex] = 1;
+ }
+ for (int i = 0; i < v - 2; i++)
+ {
+ degree[prufer[i]]++;
+ }
+
+ // pq contains all vertices of degree 1
+ MinPQ pq = new MinPQ();
+ for (int vertex = 0; vertex < v; vertex++)
+ {
+ if (degree[vertex] == 1) pq.Insert(vertex);
+ }
+
+ // repeatedly DelMin() degree 1 vertex that has the minimum index
+ for (int i = 0; i < v - 2; i++)
+ {
+ int vertex = pq.DelMin();
+ g.AddEdge(vertex, prufer[i]);
+ degree[vertex]--;
+ degree[prufer[i]]--;
+ if (degree[prufer[i]] == 1)
+ {
+ pq.Insert(prufer[i]);
+ }
+ }
+ g.AddEdge(pq.DelMin(), pq.DelMin());
+ return g;
+ }
+
+ ///
+ /// Unit tests the GraphGenerator library.
+ ///
+ ///
+ public static void RunMain(string[] args)
+ {
+ int v = int.Parse(args[0]);
+ int e = int.Parse(args[1]);
+ int v1 = v / 2;
+ int v2 = v - v1;
+
+ StdOut.PrintLn("complete graph");
+ StdOut.PrintLn(Complete(v));
+ StdOut.PrintLn();
+
+ StdOut.PrintLn("simple");
+ StdOut.PrintLn(Simple(v, e));
+ StdOut.PrintLn();
+
+ StdOut.PrintLn("Erdos-Renyi");
+ double p = e / (v * (v - 1) / 2.0);
+ StdOut.PrintLn(Simple(v, p));
+ StdOut.PrintLn();
+
+ StdOut.PrintLn("complete bipartite");
+ StdOut.PrintLn(CompleteBipartite(v1, v2));
+ StdOut.PrintLn();
+
+ StdOut.PrintLn("bipartite");
+ StdOut.PrintLn(Bipartite(v1, v2, e));
+ StdOut.PrintLn();
+
+ StdOut.PrintLn("Erdos Renyi bipartite");
+ double q = (double)e / (v1 * v2);
+ StdOut.PrintLn(Bipartite(v1, v2, q));
+ StdOut.PrintLn();
+
+ StdOut.PrintLn("path");
+ StdOut.PrintLn(Path(v));
+ StdOut.PrintLn();
+
+ StdOut.PrintLn("cycle");
+ StdOut.PrintLn(Cycle(v));
+ StdOut.PrintLn();
+
+ StdOut.PrintLn("binary tree");
+ StdOut.PrintLn(BinaryTree(v));
+ StdOut.PrintLn();
+
+ StdOut.PrintLn("tree");
+ StdOut.PrintLn(Tree(v));
+ StdOut.PrintLn();
+
+ StdOut.PrintLn("4-regular");
+ StdOut.PrintLn(Regular(v, 4));
+ StdOut.PrintLn();
+
+ StdOut.PrintLn("star");
+ StdOut.PrintLn(Star(v));
+ StdOut.PrintLn();
+
+ StdOut.PrintLn("wheel");
+ StdOut.PrintLn(Wheel(v));
+ StdOut.PrintLn();
+ }
+ }
+}