【A* + 第K短路】 poj2449 Remmarguts' Date

题意很简单,就是求从s到t的第k短路。

可以用A*算法来解决。

所以自然地,我们需要设计一个估值函数h。由于估值函数是对“剩余所需代价”的估计,所以如果我们用某点到终点的最短路径作为这个h值,就相当精确了。

自然想到以t为起点跑一遍单源最短路。

代码:

#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

const int MAX = 1024;
int dis[MAX];
struct Node {
	int id;
	int g; //cost now
	int h; //cost rest
	int f; //all cost
	Node() {

	}
	Node(int _id, int _g, int _h, int _f) {
		id = _id;
		g = _g;
		h = _h;
		f = _f;
	}
	bool operator<(const Node& B)const {
		return f > B.f;
	}
};
struct Edge {
	int to;
	int c;
	Edge() {
	}
	Edge(int a, int b): to(a), c(b) {}
};
vector<Edge> G[MAX];
vector<Edge> rG[MAX];

bool vis[MAX];
const int INF = 0xfffffff;
int djistra(int u, int n) {
	memset(vis, false, sizeof(vis));
	fill(dis, dis + n + 1, INF);
	dis[u] = 0;
	
	while (true) {
		int v = -1;
		for (int u = 1; u <= n; ++u) {
			if (!vis[u] && (v == -1 || dis[v] > dis[u])) {
				v = u;
			}
		}
		if (v == -1) break;
		
		vis[v] = true;
		for (int i = 0; i < rG[v].size(); ++i) {
			Edge &e = rG[v][i];
			if (!vis[e.to] && dis[e.to] > dis[v] + e.c) {
				dis[e.to] = dis[v] + e.c;
			}
		}
	}//while
	return 1;
}

int t_t[MAX];
int AStar(int s, int t, int k, int n) {
	
	if (s == t) ++k; //WHY ???
	
	priority_queue<Node> Q;
	while (!Q.empty()) Q.pop();
	
	memset(t_t, 0, sizeof(t_t));
	
	Node now(s, 0, dis[s], dis[s]), next;
	Q.push(now);
	
	while (!Q.empty()) {
		
		now = Q.top();
		Q.pop();//get the closest state
		
		++t_t[now.id];
		if (t_t[now.id] > k) continue;
		if (t_t[t] >= k) return now.f;
		
		for (vector<Edge>::iterator it = G[now.id].begin(); it != G[now.id].end(); ++it) {
			next.id = it->to;
			next.g = now.g + it->c;
			next.h = dis[it->to];
			next.f = next.g + next.h;
			Q.push(next);
		}
	}
	
	return -1;
}

inline int read() {
	char ch;
	while ((ch = getchar()) < '0' || ch > '9');
	int x = ch - '0';
	while ((ch = getchar()) >= '0' && ch <= '9') {
		x = (x << 3) + (x << 1) + ch - '0';
	}
	return x;
}

int main() {
	int n, m, s, t, k;
	while (~scanf(" %d %d", &n, &m)) {
		for (int i = 0; i <= n; ++i) {
			G[i].clear();
			rG[i].clear();
		}
		
		int a, b, c;
		while (m--) {
			a = read();
			b = read();
			c = read();
			//scanf(" %d %d %d", &a, &b, &c);
			G[a].push_back(Edge(b, c));
			rG[b].push_back(Edge(a, c));
		}//graph
		scanf(" %d %d %d", &s, &t, &k);
		djistra(t, n);
		printf("%d\n", AStar(s, t, k, n));
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值