题目传送门
题面里有最大值最小,所以直接想到二分答案.在检验答案时,如果dfs爆搜,会得46分.
对于题目中的两个限制:金钱和血量.金钱我们可以二分答案处理,而血量我们希望消耗的越少越好,最短路.最后和0比较看能不能活着到终点.
这道题不卡spfa.
46分代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int n,m,b,tot,head[10001];
long long a[10001],sum,num = 999999999999,ans,dis[10001];
bool flag,vis[10001];
struct kkk {
int to,next;
long long len;
}e[100001];
inline void add(int x,int y,int z) {
e[++tot].to = y;
e[tot].next = head[x];
e[tot].len = z;
head[x] = tot;
}
inline bool dp(int mid,int rt,int bl) {
queue<int> q;
memset(vis,0,sizeof(vis));
memset(dis,0x3f,sizeof(dis));
dis[rt] = 0;
q.push(rt);
vis[rt] = 1;
while(!q.empty()) {
int u = q.front();
q.pop();
vis[u] = 0;
for(int i = head[u];i; i = e[i].next) {
int o = e[i].to;
if(a[o] > mid) continue;
if(dis[o] > dis[u] + e[i].len) {
dis[o] = dis[u] + e[i].len;
if(!vis[o]) {
vis[o] = 1;
q.push(o);
}
}
}
}
if(dis[n] < bl) return 1;
return 0;
}
int main() {
scanf("%d%d%d",&n,&m,&b);
for(int i = 1;i <= n; i++) {
scanf("%lld",&a[i]);
sum = max(sum,a[i]);
num = min(num,a[i]);
}
for(int i = 1;i <= m; i++) {
int x,y;
long long z;
scanf("%d%d%lld",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
long long l = num,r = sum,mid;
while(l <= r) {
memset(vis,0,sizeof(vis));
mid = l + r >> 1;
flag = 0;
if(dp(mid,1,b))
r = mid - 1;
else
l = mid + 1;
}
if(l <= sum)
printf("%lld",l);
else printf("AFK");
return 0;
}