public Iterable<DirectedEdge> adj(int v){ return adj[v]; }
public Iterable<DirectedEdge> edges(){ Bag<DirectedEdge> bag = new Bag<>(); for (int v = 0; v < V; v++) for (DirectedEdge edge : adj[v]) bag.add(edge); return bag; } ··· }
publicclassAcyclicSP{ ··· publicAcyclicSP(EdgeWeightedDigraph G, int s){ ··· Topological top = new Topological(G); for (int v : top.order()) relax(G, v); } ··· }
publicclassCPM{ publicstaticvoidmain(String[] args){ int N = StdIn.readInt(); StdIn.readLine(); EdgeWeightedDigraph G = new EdgeWeightedDigraph(2 * N + 2); int s = N * 2, t = N * 2 + 1;//s起点,t终点,0~2N所有顶点 for (int i = 0; i < N; i++) { String[] a = StdIn.readLine().split("\\s+"); double duration = Double.parseDouble(a[0]); G.addEdge(new DirectedEdge(i, i + N, duration)); G.addEdge(new DirectedEdge(s, i, 0.0)); G.addEdge(new DirectedEdge(i + N, t, 0.0)); for (int j = 1; j < a.length; j++) { int successor = Integer.parseInt(a[j]); G.addEdge(new DirectedEdge(i + N, successor, 0.0)); } } AcyclicLP lp = new AcyclicLP(G, s); System.out.println("Start times:"); for (int i = 0; i < N; i++) System.out.printf("%d: %5.1f\n", i, lp.distTo(i)); System.out.printf("Finish time: %5.1f\n", lp.distTo(t)); } }
privatevoidrelax(EdgeWeightedDigraph G, int v){ for (DirectedEdge edge : G.adj(v)) { int w = edge.to(); if (distTo[w] > distTo[v] + edge.weight()) { distTo[w] = distTo[v] + edge.weight(); edgeTo[w] = edge; if (!onQ[w]) { queue.enqueue(w); onQ[w] = true; } } if (cost++ % G.V() == 0) findNegativeCycle();//周期性寻找负权重环 } }
寻找负权重环
这里采用EdgeWeightedDirectedCycle(最短路径中拓扑排序)来检测加权有向环。
findNegativeCycle() 寻找负权重环
1 2 3 4 5 6 7 8 9 10
publicvoidfindNegativeCycle(){ int V = edgeTo.length; EdgeWeightedDigraph spt; spt = new EdgeWeightedDigraph(V); for (DirectedEdge edge : edgeTo) if (edge != null) spt.addEdge(edge); EdgeWeightedDirectedCycle finder = new EdgeWeightedDirectedCycle(spt); cycle = finder.cycle(); }