搜索_A*_POJ2449_Remmarguts' Date

版权声明:本文为博主原创作品, 转载请注明出处! https://blog.csdn.net/solider98/article/details/84346525

点此打开题目页面

思路分析:

    如果直接使用优先队列BFS,将导致的一个直接结果就是内存爆, 考虑采用A*, 使用的估价函数为当前扩展结点x到目标结点T的最短路径, 因此需先预处理所有结点到T的最短路径距离, 这可采用在给定图的转置图上计算结点T到所有结点的最短距离. 可以证明第K次从优先队列中取出点T对应的距离为点S到T的第K短路的长度, 在此基础上给出如下AC代码(注意第38行的if(S == T) ++K; 是必要的, 原因不详):

//POJ2449_Remmarguts' Date
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
#include <vector>
#include <functional>
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef pair<int, int> pii; typedef pair<pii, int> piii;
const int MAXN = 1e3 + 5, MAXM = 1e5 + 5, INF = 0x3f3f3f3f;
int N, M, S, T, K; int ver[MAXM << 1], nex[MAXM << 1], we[MAXM << 1], head[MAXN], tot;
int tver[MAXM << 1], tnex[MAXM << 1], twe[MAXM << 1], thead[MAXN], ttot;//转置图信息 
int mind[MAXN]; 
//计算转置图中各顶点到T的最短距离
void calcMind(){
	priority_queue<pii, vector<pii>, greater<pii> > pq; 
	pq.push(mp(0, T)); memset(mind, 0x3f, sizeof(mind));
	while(!pq.empty()){
		int a = pq.top().fi, b = pq.top().se; pq.pop();
		if(mind[b] != INF) continue; mind[b] = a;
		for(int i = thead[b], y; i; i = tnex[i]) 
			if(y = tver[i], mind[y] == INF) pq.push(mp(a + twe[i], y));
	}
}
int main(){
	scanf("%d %d", &N, &M);
	for(int i = 1; i <= M; ++i){
		int u, v, w; scanf("%d %d %d", &u, &v, &w);
		ver[++tot] = v, we[tot] = w;
		if(!head[u]) head[u] = tot; else nex[tot] = head[u], head[u] = tot;
		tver[++ttot] = u, twe[ttot] = w;
		if(!thead[v]) thead[v] = ttot; else tnex[ttot] = thead[v], thead[v] = ttot;
	}
	scanf("%d %d %d", &S, &T, &K), calcMind(); int cnt = 0, res = INF;  if(S == T) ++K;
	priority_queue<piii, vector<piii>, greater<piii> > pq; pq.push(mp(mp(mind[S], 0), S));
	while(!pq.empty()){
		int a = pq.top().fi.se, b = pq.top().se; pq.pop();
		if(b == T) ++cnt, res = a; if(cnt == K) break;
		for(int i = head[b]; i; i = nex[i]){
			int y = ver[i], z = a + we[i]; pq.push(mp(mp(mind[y] + z, z), y));
		} 
	}
	if(cnt == K) cout << res << endl; else cout << -1 << endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/solider98/article/details/84346525