[题解] poj 2449 Remmarguts' Date (dijkstra最短路+A*搜索)

- 传送门 -

 http://poj.org/problem?id=2449

#Remmarguts' Date

| Time Limit: 4000MS |   | Memory Limit: 65536K |
| Total Submissions: 30603 |   | Accepted: 8361 |

Description

"Good man never makes girls wait or breaks an appointment!" said the mandarin duck father. Softly touching his little ducks' head, he told them a story.

"Prince Remmarguts lives in his kingdom UDF – United Delta of Freedom. One day their neighboring country sent them Princess Uyuw on a diplomatic mission."

"Erenow, the princess sent Remmarguts a letter, informing him that she would come to the hall and hold commercial talks with UDF if and only if the prince go and meet her via the K-th shortest path. (in fact, Uyuw does not want to come at all)"

Being interested in the trade development and such a lovely girl, Prince Remmarguts really became enamored. He needs you - the prime minister's help!

DETAILS: UDF's capital consists of N stations. The hall is numbered S, while the station numbered T denotes prince' current place. M muddy directed sideways connect some of the stations. Remmarguts' path to welcome the princess might include the same station twice or more than twice, even it is the station with number S or T. Different paths with same length will be considered disparate.

Input

The first line contains two integer numbers N and M (1 <= N <= 1000, 0 <= M <= 100000). Stations are numbered from 1 to N. Each of the following M lines contains three integer numbers A, B and T (1 <= A, B <= N, 1 <= T <= 100). It shows that there is a directed sideway from A-th station to B-th station with time T.

The last line consists of three integer numbers S, T and K (1 <= S, T <= N, 1 <= K <= 1000).

Output

A single line consisting of a single integer number: the length (time required) to welcome Princess Uyuw using the K-th shortest path. If K-th shortest path does not exist, you should output "-1" (without quotes) instead.

Sample Input

2 2
1 2 5
2 1 4
1 2 2

Sample Output

14

Source

POJ Monthly,Zeyuan Zhu

[[Submit](http://poj.org/submit?problem_id=2449)]   [[Status](http://poj.org/problemstatus?problem_id=2449)]   [[Discuss](http://poj.org/bbs?problem_id=2449)]

- 题意 -

 求有向图中第k短路(可重复走).
 

- 思路 -

 (A^*)算法的讲解: http://www.cppblog.com/mythit/archive/2009/04/19/80492.aspx
 
 本题中(A^*)的运用我觉得就是在优化BFS, 队列中的元素(x)我们设有ST[x]表示从起点出发到 x 点已走的路径, EN[x]表示 x 距离终点的最短路径. 则队列中元素按G[x] = ST[x]+EN[x]从小到大排列, 每次取出最小的G[x], 将 x 可以到达的点插入队列中(他们的路径是从 x 走到的, 依靠 G[x] 来更新这些点的G), 直到终点被取出第 k 次时有解(说明找到了 k 种不同路径通向终点).
 EN[x]要用反向边预处理最短路.
 
 细节见代码.
 

- 代码 -

#include<cstdio>
#include<queue>
#include<cstring>
#define ft first
#define sd second
using namespace std;

typedef pair<int, int> pii;
const int N = 1e3 + 5;
const int M = 1e5 + 5;

int TO[M], NXT[M], V[M], HD[N];
int re_TO[M], re_NXT[M], re_V[M], re_HD[N];
int DIS[N], VIS[N];
int n, m;
int sz, re_sz;

struct ASTAR {
	int v, pos;
	bool operator < (const ASTAR &tmp) const {
		return DIS[v] + pos > DIS[tmp.v] + tmp.pos;
	}
};

void add(int x, int y, int v) {
	TO[++re_sz] = y; V[re_sz] = v;
	NXT[re_sz] = HD[x]; HD[x] = re_sz;
}

void re_add(int x, int y, int v) {
	re_TO[++sz] = y; re_V[sz] = v;
	re_NXT[sz] = re_HD[x]; re_HD[x] = sz;
}

void dijkstra(int x) {
	priority_queue<pii, vector<pii>, greater<pii> >Q;
	memset(DIS, 0x3f, sizeof (DIS));
	DIS[x] = 0;
	pii st = make_pair(0, x);
	Q.push(st);
	while (!Q.empty()) {
		pii x = Q.top();
		Q.pop();
		int u = x.sd;
		if (VIS[u]) continue;
		VIS[u] = 1;
		for (int i = re_HD[u]; i; i = re_NXT[i]) {
			int v = re_TO[i];
			if (!VIS[v] && DIS[v] > DIS[u] + re_V[i]) {
				DIS[v] = DIS[u] + re_V[i];
				pii y = make_pair(DIS[v], v);
				Q.push(y);
			}
		}
	}
}

int astar(int x, int y, int k) {
	if (x == y) k ++; //注意起点终点相同时, 一开始只有起点在队列中, 会被多计算一次.
	priority_queue<ASTAR>Q;
	ASTAR st;
	st.v = x; st.pos = 0;
	Q.push(st);
	while (!Q.empty()) {
		ASTAR x = Q.top();
		Q.pop();
		int u = x.v;
		if (u == y) {
			-- k;
			if (!k)
				return x.pos;
		}
		for (int i = HD[u]; i; i = NXT[i]) {
			int v = TO[i];
			ASTAR w;
			w.v = v; w.pos = x.pos + V[i];
			Q.push(w);
		}
	}
	return -1;
}

int main() {
	int x, y, v;
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= m; ++ i) {
		scanf("%d%d%d", &x, &y, &v);
		add(x, y, v);
		re_add(y, x, v);
	}
	scanf("%d%d%d", &x, &y, &v);
	dijkstra(y);
	if (DIS[x] == 0x3f3f3f3f) {
		printf("%d
", -1); //注意起点终点不连通的情况
		return 0;
	}
	printf("%d
", astar(x, y, v));
	return 0;
}
原文地址:https://www.cnblogs.com/Anding-16/p/7392069.html