POJ2449 Remmarguts' Date

一. 原题链接:http://poj.org/problem?id=2449

二. 题目大意:给一个有向图,给出S(起点)和T(终点),让你求第K短路。

三. 思路:启发式搜索A*算法+SPFA求最短路做为H[]估值函数。

先建立原图的反向图,用SPFA算法,求出图中各点到源点的最短路径。

A*算法有2个函数G(x)和H(x),G(x)表示从起点到该点x的路径长度,H(x)表示从该点到终点的最短路径。

A*算法步骤:

1.计算起点的G(x)(也就是0)和H(x),将其加入优先级队列(优先级队列优先级为G(x)+H(x),小的话先出。)

2.在优先级队列不为空时,一直弹出队首,对于每个队首元素,进行如下操作:

遍历与其连接的每个点,更新每个店的G(x)和H(x),将其压入优先级队列。

3.当第k次寻找到终点,G(x)+H(x)的值就是第K短路的路径长度。

4.若未到第k次,队列就为空,说明不存在第K短路,输出-1。

利用优先队列维护,相当于A*算法中所谓开启列表,而这题没有关闭列表,因为要搜多条路径。

其实这题的A*算法说白了,就是在BFS的基础上,队列使用优先队列。再加上寻找到第K次才退出,总体难度还是不难,但是由于太久没做还有强行用Java的原因,做了一个晚上加上一个早上。

四.注意点:

1. 有重边,不要考虑邻接矩阵。

2. S==T的时候,先k++。因为当S==T的时候,要算先走一次。

五.代码:

//POJ2449
import java.util.*;

class Main {
	final static int MAX_SIZE = 1010;
	final static int INF = 0x3f3f3f3f;
	
	static class Node{
		public int v;
		public int weight;
	}
	
	static List<Node> Graph[] = new ArrayList[MAX_SIZE];
	static List<Node> reGraph[] = new ArrayList[MAX_SIZE];
	static int nodeNum;
	static int edgeNum;
	static int k;

	static int[] SPFA(int start, int end){
		int dist[] = new int[nodeNum+1];
		boolean inQue[] = new boolean[nodeNum+1];
		Queue<Integer> que = new LinkedList<Integer>();
		
		int i, cur;
		for (i = 0; i < nodeNum+1; i++){
			dist[i] = INF;
			inQue[i] = false;
		}
		dist[start] = 0;
		que.offer(start);
		inQue[start] = true;
		
		while (!que.isEmpty()) {
			cur = que.poll(); 
			inQue[cur] = false;
			Iterator<Node> it = reGraph[cur].iterator();
			while (it.hasNext()){
				Node node = it.next();
				int v = node.v;
				int weight = node.weight;
				
				if (dist[v] > dist[cur] + weight){
					dist[v] = dist[cur] + weight;
					if (!inQue[v]){
						inQue[v] = true;
						que.offer(v);
					}
				}
			}
		}
		
		return dist;
	}
	
	static int AStar(int start, int end, int []H){
		class Point{
			public int id;
			public int h;
			public int g;
		}
		
		Comparator<Point> order = new Comparator<Point>(){
			public int compare(Point a, Point b){
				int fa = a.g + a.h;
				int fb = b.g + b.h;
				return fa>fb? 1:(fa==fb?0:-1);
			}
		};
		
		Queue<Point> que = new PriorityQueue<Point>(nodeNum, order);
		Point cur = new Point();
		cur.g = 0;
		cur.h = H[start];
		cur.id = start;
		
		que.offer(cur);
		int cnt = 0;
		
		while(!que.isEmpty()){
			cur = que.poll();
			
			if (cur.id == end){
				cnt++;
				
				if (cnt == k){
					return cur.g + cur.h;
				}
			}
			
			Iterator<Node> it = Graph[cur.id].iterator();

			while(it.hasNext()){
				Node tmp = it.next();
				int v = tmp.v;
				int weight = tmp.weight;
				Point nextP = new Point();
				nextP.g = cur.g + weight;
				nextP.h = H[v];
				nextP.id = v;
				
				que.offer(nextP);
			}
		}
		
		return -1;
	}
	
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		nodeNum = in.nextInt();
		edgeNum = in.nextInt();
		
		int u, v, w, i;
		for (i = 1; i <= nodeNum; i++)
			Graph[i] = new ArrayList<Node>();
		
		for (i = 1; i <= nodeNum; i++)
			reGraph[i] = new ArrayList<Node>();
		
		for (i = 0; i < edgeNum; i++){
			u = in.nextInt();
			v = in.nextInt();
			w = in.nextInt();
			Node newNode = new Node();
			newNode.v = v;
			newNode.weight = w;
			Graph[u].add(newNode);
			//反向图
			Node newNodeForRe = new Node();
			newNodeForRe.v = u;
			newNodeForRe.weight = w;
			reGraph[v].add(newNodeForRe);
		}
		
		int start, end;
		start = in.nextInt();
		end = in.nextInt();
		k = in.nextInt();
		
		int dist[] = SPFA(end, start);
		if (start == end)
			k++;
		System.out.println(AStar(start, end, dist));
		
		in.close();
	}
	
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值