很经典的一道题目,第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);
- }
- }