题目链接:
https://www.luogu.org/problem/show?pid=1462
题意:
题解:
二分法+最短路判定。
二分经过城市的最大费用w,然后判定:对于每一个费用大于w的城市标记为不可达,求最短路径,判断最短路与血量的关系即可。如果一个城市不可达可以在SPFA算法开始前将inq置为1。
小的优化:把f值从小到大排序,对f值进行二分就可以了。
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 #define MS(a) memset(a,0,sizeof(a)) 5 #define MP make_pair 6 #define PB push_back 7 const int INF = 0x3f3f3f3f; 8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; 9 inline ll read(){ 10 ll x=0,f=1;char ch=getchar(); 11 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 13 return x*f; 14 } 15 ////////////////////////////////////////////////////////////////////////// 16 const int maxn = 1e5+10; 17 18 int n,m,B; 19 ll f[maxn],x[maxn]; 20 vector<pair<int,int> > E[maxn]; 21 int inq[maxn]; ll d[maxn]; 22 queue<int> q; 23 bool check(ll w){ 24 MS(inq); 25 for(int i=1; i<=n; i++){ 26 d[i] = INFLL; 27 if(f[i] > w) inq[i] = 1; // 好神奇撒 到达了i这个点 也不会从i出发,保证i不可到达,特判终点就好了 28 } 29 30 if(f[1]>w || f[n]>w) return false; 31 32 queue<int> q; 33 q.push(1),inq[1]=1,d[1]=0; 34 while(!q.empty()){ 35 int now = q.front(); q.pop(); 36 inq[now] = 0; 37 for(int i=0; i<(int)E[now].size(); i++){ 38 int v = E[now][i].first; ll b = E[now][i].second; 39 if(d[v] > d[now]+b){ 40 d[v] = d[now]+b; 41 if(inq[v]) continue; 42 inq[v] = 1; 43 q.push(v); 44 } 45 } 46 } 47 return B >= d[n]; 48 } 49 50 int main(){ 51 cin >> n >> m >> B; 52 for(int i=1; i<=n; i++) cin>>f[i]; 53 for(int i=1; i<=m; i++){ 54 int u,v,w; cin>>u>>v>>w; 55 E[u].push_back(MP(v,w)); 56 E[v].push_back(MP(u,w)); 57 } 58 59 memcpy(x,f,sizeof(f)); 60 sort(x+1,x+n+1); 61 int L = 1, R = n; 62 ll ans = INFLL; 63 while(L <= R){ 64 int mid = (L+R)/2; 65 if(check(x[mid])) ans=x[mid],R=mid-1; 66 else L=mid+1; 67 } 68 69 if(ans==INFLL) puts("AFK"); 70 else cout << ans << endl; 71 72 return 0; 73 }