思路
对于不能到达的情况,直接跑一遍$SPFA$就可以了
使得最大值最下,这不是典型的二分答案吗
二分最大的费用
后面用$SPFA$实现,只需要在进行松弛操作的时候进行一下调整
使得所有沿途的点的话费都小于这个二分出来的花费
代码
#include <iostream> #include <cstdio> #include <algorithm> #include <queue> #include <cstring> #define MAXN 10007 #define MAXm 100007 #define INF 2147483647 #define int long long using namespace std; int n, m, b, f[MAXN], first[MAXN], dis[MAXN], s = 1; int u[MAXm], v[MAXm], w[MAXm], next[MAXm], maxn, Ans; bool vis[MAXN]; deque<int> Q; bool SPFA(int s, int p) { if(f[1] >= p) return false; memset(vis, false, sizeof(vis)); for(int i=1; i<=n; i++) {dis[i] = INF;} dis[s] = 0; while(!Q.empty()) {Q.pop_front();} Q.push_front(s); vis[s] = 1; while(!Q.empty()) { int x = Q.front(); int k = first[Q.front()]; Q.pop_front(); while(k != -1) { if(dis[v[k]] > dis[u[k]]+w[k]&&f[v[k]] <= p) { dis[v[k]] = dis[u[k]]+w[k]; if(!vis[v[k]]) { vis[v[k]] = 1; if(dis[v[k]] > dis[x]) Q.push_back(v[k]); else Q.push_front(v[k]); } } k = next[k]; } vis[x] = 0; } if(dis[n] < b) return true; else return false; } main() { scanf("%lld%lld%lld", &n, &m, &b); for(int i=1; i<=n; i++) {scanf("%lld", &f[i]); maxn = max(maxn, f[i]);} memset(first, -1, sizeof(first)); for(int i=1; i<=n; i++) {dis[i] = INF;} dis[s] = 0; for(int i=1; i<=2*m; i++) { scanf("%lld%lld%lld", &u[i], &v[i], &w[i]); next[i] = first[u[i]]; first[u[i]] = i; i++; u[i] = v[i-1], v[i] = u[i-1], w[i] = w[i-1]; next[i] = first[u[i]]; first[u[i]] = i; } int l = 1, r = maxn; bool mark = false; while(l <= r) { int mid = (l+r)/2; if(SPFA(1, mid)) { r = mid-1; mark = true; } else l = mid+1; } if(mark == false) printf("AFK"); else printf("%lld ", l); return 0; }