很经典的一道题目,第K最短路,很多应用都会用到的一个小算法。然后解法也很多,这里用了Dijkstra+A*搜索,每次从最小堆中弹出"c[x]+f[x]"值最小的结点x来继续访问,其中c[x]为从起点访问到x点的距离,f[x]为从x点到终点的最短距离。
不过为了AC这道题目,倒是犯了几个小错误:
1:根据题目,就算给定的起点s==给定的终点t,那么必须也要走,最短路径不能为0,所以就有了讨论中很多人说的那句代码 if(s==t)k++;
2:这个错误我也搞不清楚状况,主要是用Dijkstra计算所有点到终点的最短路径时候,我一开始的代码如下,一直是wrong answer。
funcArr[beg-1] = 0; visFlag[beg-1] = true; PriorityQueue<HeapNode> queue = new PriorityQueue<HeapNode>(graph.size(),new Comp1()); for(int i=0;i<graph.get(beg-1).lNodes.size();i++) { LinkNode tlNode = graph.get(beg-1).lNodes.get(i); funcArr[tlNode.lid-1] = tlNode.t; queue.add(new HeapNode(tlNode.lid, funcArr[tlNode.lid-1])); }
改为如下就AC了。难道是最近没有常写代码,都愚钝了。
funcArr[beg-1] = 0; PriorityQueue<HeapNode> queue = new PriorityQueue<HeapNode>(graph.size(),new Comp1()); queue.add(new HeapNode(beg, 0));
最终AC的完整代码:
import java.util.*; class Node { public Node() { lNodes = new ArrayList<LinkNode>(); } public ArrayList<LinkNode> lNodes; } class LinkNode { public LinkNode() { lid = 0; t = 0; } public LinkNode(int linkId, int time) { lid = linkId; t = time; } public int lid; public int t; } class HeapNode { public HeapNode(int nid,int cv) { this.nodeId = nid; this.cvalue = cv; } public HeapNode() { } public HeapNode(int nid, int cv, int fv) { nodeId = nid; cvalue = cv; fvalue = fv; } public int nodeId; public int cvalue; public int fvalue; } class Comp1 implements Comparator<HeapNode> { public int compare(HeapNode arg0, HeapNode arg1) { return arg0.cvalue - arg1.cvalue; } } class Comp2 implements Comparator<HeapNode> { public int compare(HeapNode arg0, HeapNode arg1) { return (arg0.cvalue + arg0.fvalue) - (arg1.cvalue + arg1.fvalue); } } public class Main { final static int MAX = 1<<30; public static int[] Dijkstra(ArrayList<Node> graph, int beg) { int n = graph.size(); int funcArr[] = new int[n]; boolean visFlag[] = new boolean[n]; for(int i=0;i<n;i++) { funcArr[i] = MAX; visFlag[i] = false; } funcArr[beg-1] = 0; PriorityQueue<HeapNode> queue = new PriorityQueue<HeapNode>(graph.size(),new Comp1()); queue.add(new HeapNode(beg, 0)); while(queue.isEmpty() == false) { HeapNode tnode = queue.poll(); if(visFlag[tnode.nodeId-1] == true) continue; visFlag[tnode.nodeId-1] = true; for(int i=0;i<graph.get(tnode.nodeId - 1).lNodes.size();i++) { LinkNode tlnode = graph.get(tnode.nodeId-1).lNodes.get(i); if(funcArr[tnode.nodeId - 1] + tlnode.t < funcArr[tlnode.lid-1]) { funcArr[tlnode.lid-1] = funcArr[tnode.nodeId - 1] + tlnode.t; queue.add(new HeapNode(tlnode.lid, funcArr[tlnode.lid-1])); } } } return funcArr; } public static int AStartKShortestPath(ArrayList<Node> graph, int beg, int end,int k,int[] funcArr) { if(beg==end)k++; int dis = -1; int kcount = 0; int n = graph.size(); PriorityQueue<HeapNode> queue = new PriorityQueue<HeapNode>(n,new Comp2()); queue.add( new HeapNode(beg,0,funcArr[beg-1])); while(queue.isEmpty() == false) { HeapNode hNode= queue.poll(); if(hNode.nodeId == end)kcount++; if(kcount == k) { //System.out.println(hNode.nodeId+":"+hNode.cvalue+","+hNode.fvalue); dis = hNode.cvalue + hNode.fvalue; break; } for(int i=0;i<graph.get(hNode.nodeId-1).lNodes.size();i++) { LinkNode tlNode = graph.get(hNode.nodeId-1).lNodes.get(i); if(funcArr[tlNode.lid-1] < MAX) { HeapNode tmphnode = new HeapNode(tlNode.lid, hNode.cvalue + tlNode.t, funcArr[tlNode.lid-1]); queue.add(tmphnode); } } } return dis; } public static void main(String[] args) { //Initialize the graph and transpose graph////////////////////// Scanner scan = new Scanner(System.in); int n,m; n = scan.nextInt(); m = scan.nextInt(); ArrayList<Node> graph = new ArrayList<Node>(n); ArrayList<Node> tgraph = new ArrayList<Node>(n); for(int i=0;i<n;i++) { graph.add(new Node()); tgraph.add(new Node()); } for(int i=0;i<m;i++) { int b,e,t; b = scan.nextInt(); e = scan.nextInt(); t = scan.nextInt(); //Graph LinkNode tn0 = new LinkNode(e,t); graph.get(b-1).lNodes.add(tn0); //Transpose graph LinkNode tn1 = new LinkNode(b,t); tgraph.get(e-1).lNodes.add(tn1); } int s,t,k; s = scan.nextInt(); t = scan.nextInt(); k = scan.nextInt(); ///////////////////////////////////////////// int[] funcArr = Dijkstra(tgraph, t); int dis = AStartKShortestPath(graph, s, t, k, funcArr); System.out.println(dis); } }