题目传送
无数发wa之后终于过了。
方法:dijkstral+二分
详解:将过路费排列后枚举,判断是否可行。以伤害作为边的权值,找最短路,并判断血量是否足够。
二分之前,先用最大路费判断,若最大路费都不可通过,则无解。
#include
#include
#include
#include
#define maxn 10000+10
#define maxm 50010
#define inf 1000000000+100
using namespace std;
struct edgs {
//边
int from, to, cost, next;
} edg[maxm * 2];
struct node {
//作为队列的类型
int d, u;
node(int a, int b) :d(a), u(b) {
}
bool operator<(const node& p) const {
return d > p.d;
}
};
int n, m, tot, cnt;
int f[maxn], an[maxn]; //费用
int d[maxn]; //血
int used[maxn]; //标记
int head[maxn]; //邻接矩阵头
void addedgs(int from, int to, int cost)
{
cnt++;
edg[cnt].from = from;
edg[cnt].to = to;
edg[cnt].cost = cost;
edg[cnt].next = head[from];
head[from] = cnt;
return;
}
bool cheak(int top)
{
if (f[1] > top || f[n] > top) return false;
for (int i = 1; i <= n; i++) {
d[i] = inf;
used[i] = 0;
}
d[1] = 0;
priority_queue<node> q;
q.push(node(0, 1));
while (q.size()) {
int u = q.top().u;
q.pop();
if (used[u]) continue;
used[u] = 1;
for (int i = head[u]; i; i = edg[i].next) {
if (d[edg[i].to] > d[u] + edg[i].cost && f[edg[i].to] <= top) {
d[edg[i].to] = d[u] + edg[i].cost;
q.push(node(d[edg[i].to], edg[i].to));
}
}
}
if (d[n] <= tot) return true;
else return false;
}
int main(void)
{
ios::sync_with_stdio(false);
cin >> n >> m >> tot;
for (int i = 1; i <= n; i++) {
cin >> f[i];
an[i] = f[i];
}
sort(an + 1, an + n + 1);
for (int i = 1; i <= m; i++) {
int a, b, c;
cin >> a >> b >> c;
addedgs(a, b, c);
addedgs(b, a, c);
}
if (cheak(an[n]) == false) {
//判断最大费用能否到达
cout << "AFK";
return 0;
}
int l = 1, r = n, ans = an[n];
while (l <= r) {
//二分
int mid = (l + r) / 2;
if (cheak(an[mid])) {
ans = an[mid];
r = mid - 1;
}
else l = mid + 1;
}
cout << ans;
return 0;
}