/// <summary> /// init /// </summary> /// <param name="g"></param> /// <param name="source"></param> protected void Init(EdgeWeightedDigraph g, int source) { this.source = source; edgeTo = new DirectedEdge[g.V]; distTo = new double[g.V]; for (int i = 0; i < g.V; i++) { distTo[i] = double.NegativeInfinity; } distTo[source] = 0; }
/// <summary> /// constructor /// </summary> /// <param name="g"></param> /// <param name="source"></param> public SingleSourceShortPath(EdgeWeightedDigraph g, int source) { this.source = source; edgeTo = new DirectedEdge[g.V]; distTo = new double[g.V]; for (int i = 0; i < g.V; i++) { //for simplicity, we don't init to positiveInfinity, because of overflow. distTo[i] = double.PositiveInfinity / 2; } distTo[source] = 0; }
public DagShortestPaths(EdgeWeightedDigraph g, int source) : base(g, source) { TopologicalSort topological = new TopologicalSort(g); List <int> list = topological.GetTopoSort(); foreach (var i in list) { foreach (DirectedEdge e in g.Adj(i)) { base.Relax(e); } } }
/// <summary> /// reverse graph /// </summary> /// <returns></returns> public EdgeWeightedDigraph Reverse() { EdgeWeightedDigraph g = new EdgeWeightedDigraph(v); g.e = e; for (int i = 0; i < adj.Length; i++) { foreach (DirectedEdge edge in adj[i]) { g.adj[edge.To].Add(new DirectedEdge(edge.To, edge.From, edge.Weight)); } } return(g); }
/// <summary> /// constructor /// /// it runs at O(V^2*E) /// </summary> /// <param name="g"></param> public AllPairShortestPathsUsingBellmanFordAlgorithm(EdgeWeightedDigraph g) : base(g) { for (int start = 0; start < g.V; start++) { BellmanFordAlgorithm bellmanFord = new BellmanFordAlgorithm(g, start); for (int to = 0; to < g.V; to++) { if (bellmanFord.IsHavePathTo(to)) { hasPathTo[start, to] = true; weights[start, to] = bellmanFord.DistTo(to); pathTo[start, to] = bellmanFord.PathTo(to).ToList(); } } } }
/// <summary> /// constructor /// </summary> /// <param name="g"></param> public AllPairShortestPaths(EdgeWeightedDigraph g) { int n = g.V; weights = new double[n, n]; hasPathTo = new bool[n, n]; pathTo = new List <DirectedEdge> [n, n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { //for simplicity,no deal with PositiveInfinity+something weights[i, j] = i == j?0:double.PositiveInfinity / 2; } } }
private void dfs(EdgeWeightedDigraph g, int s) { nodes[s].Color = VertexColor.Gray; nodes[s].Discovered = ++time; foreach (DirectedEdge e in g.Adj(s)) { int w = e.To; if (nodes[w].Color == VertexColor.White) { nodes[w].Parent = nodes[s]; dfs(g, w); } } nodes[s].Color = VertexColor.Black; nodes[s].Finished = ++time; postOrder.Enqueue(s); }
public TopologicalSort(EdgeWeightedDigraph g) { postOrder = new Queue <int>(); nodes = new VertexNode[g.V]; for (int i = 0; i < nodes.Length; i++) { nodes[i] = new VertexNode(i); nodes[i].Color = VertexColor.White; } for (int i = 0; i < g.V; i++) { if (nodes[i].Color == VertexColor.White) { dfs(g, i); } } }
public DijkstraAlgorithm(EdgeWeightedDigraph digraph, int source) : base(digraph, source) { //pq maintain a set of vertex need to deal with. IndexMinPQ <double> pq = new IndexMinPQ <double>(digraph.V); pq.Insert(source, distTo[source]); while (!pq.IsEmpty()) { //when v pops up, the distance and path to v have been confirmed int v = pq.DelMin(); foreach (DirectedEdge e in digraph.Adj(v)) { Relax(pq, e); } } }
/// <summary> /// check Digraph is valid /// </summary> /// <param name="g"></param> /// <returns></returns> public bool IsValid(EdgeWeightedDigraph g) { if (g == null || g.V <= 0) { return(false); } foreach (DirectedEdge e in g.Edges()) { if (e.Weight < 0) { return(false); } } //TODO: add other check here return(true); }
/// <summary> /// constructor /// for any vertex v reachable from s, the path must at most v-1 edges. /// we can get (vi-1,vi) in sequence because if p = (v0,v1,...,vk) is shortest path from s =v0 to vk, we relax the edges of p in order (v0,v1) (v1,v2) (vk-1,vk), then we can get the distTo /// <param name="g"></param> /// <param name="source"></param> public BellmanFordAlgorithm(EdgeWeightedDigraph g, int source) : base(g, source) { List <DirectedEdge> edges = g.Edges(); for (int i = 0; i < g.V - 1; i++) { foreach (DirectedEdge e in edges) { base.Relax(e); } } //assume this is negative cycle (v0,v1,...vk) vk=v0. then there must be at least one distTo[e.To] > distTo[e.From] + e.Weight if (edges.Any(e => distTo[e.To] > distTo[e.From] + e.Weight)) { IsNegativeCycle = true; throw new Exception("there is negative cycle"); } }
/// <summary> /// constructor /// </summary> /// <param name="g"></param> public MaxFlowFordFulkersonMethod(EdgeWeightedDigraph g) { if (!IsValid(g)) { throw new ArgumentException(); } int n = g.V; flow = new double[n, n]; /* * while there exists a path from s to t in the residual neteork Gf * C(p) = min{Cf(u,v): (u,v) is in p} * for each edge (u,v) in p * if(u,v)∈E * (u,v).f = (u,v).f + C(p) * else * (v,u).f = (v,u).f - C(p) */ }
public static double Cp(List <Job> jobs) { //the job id start from 0 to n-1 int n = jobs.Count; for (int i = 0; i < n; i++) { jobs[i].JobID = i; } //source and sink vertex int source = 2 * n; int sink = 2 * n + 1; //build graph EdgeWeightedDigraph g = new EdgeWeightedDigraph(2 * n + 2); for (int i = 0; i < n; i++) { //add edge from source to the start of job g.AddEdge(new DirectedEdge(source, i, 0)); //add edge from the end of job to sink g.AddEdge(new DirectedEdge(i + n, sink, 0)); //add edge from the start of job to the end of job and weight duration g.AddEdge(new DirectedEdge(i, i + n, jobs[i].Duration)); foreach (var job in jobs[i].Constaints) { g.AddEdge(new DirectedEdge(job.JobID + n, i, 0)); } } //compute longest paths from source to sink DagLogestPaths paths = new DagLogestPaths(g, source); return(paths.DistTo(sink)); }