题解
题目大意,给一个有向图,问起点到终点的k短路代价是否小于t。
使用A*算法求解,由于是有向图使用dijkstra得到其它所有点到终点的最短路时需要建立反向边。
给定的有向图不一定能从起点到达终点,在使用A*之前先判断是否可达,否则会造成死循环。
AC代码
#include <stdio.h>
#include <bits/stdc++.h>
#define fst first
#define sed second
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e4 + 10;
int n, m, st, ed, k, t;
bool vis[N];
ll dis[N];
struct edge
{
int v, nxt;
ll w;
}e[N], re[N];
int h[N], rh[N], idx;
void AddEdge(int u, int v, ll w)
{
e[++idx] = { v, h[u], w };
h[u] = idx;
re[idx] = { u, rh[v], w }; //反向边
rh[v] = idx;
}
struct node
{
int v;
ll g, h; //s到v v到t f = g + h
bool operator < (const node &oth) const
{
return g + h > oth.g + oth.h;
}
};
void Dijkstra()
{
memset(dis, 0x3f, sizeof(dis));
memset(vis, 0, sizeof(vis));
dis[ed] = 0;
priority_queue<node> pq;
pq.push({ ed, 0, 0 });
while (!pq.empty())
{
int u = pq.top().v, v;
ll d = pq.top().h, w; pq.pop(); //存h内
vis[u] = 1;
for (int i = rh[u]; i; i = re[i].nxt) //跑反向边
{
v = re[i].v, w = re[i].w;
if (!vis[v] && d + w < dis[v])
dis[v] = d + w, pq.push({ v, 0, dis[v] });
}
}
}
ll AStar()
{
Dijkstra(); //以ed为起点计算h值
if (dis[st] == LINF) //无最短路
return -1;
priority_queue<node> pq;
pq.push({ st, 0, 0 });
while (!pq.empty())
{
int u = pq.top().v, v;
ll d = pq.top().g, w; pq.pop(); //g
if (u == ed && --k == 0) //是终点且是第k次到
return d;
for (int i = h[u]; i; i = e[i].nxt)
{
v = e[i].v, w = e[i].w;
pq.push({ v, d + w, dis[v] });
}
}
return -1;
}
int main()
{
#ifdef LOCAL
//freopen("C:/input.txt", "r", stdin);
#endif
while (cin >> n >> m)
{
idx = 0;
memset(h, 0, sizeof(h));
memset(rh, 0, sizeof(rh));
cin >> st >> ed >> k >> t;
for (int i = 1; i <= m; ++i)
{
int u, v;
ll w;
scanf("%d%d%lld", &u, &v, &w);
AddEdge(u, v, w);
}
ll res = AStar();
if (res == -1 || res > t)
printf("Whitesnake!\n");
else
printf("yareyaredawa\n");
}
return 0;
}