题意很简单,就是求从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;
}