本题的描述仍是很清晰的,彻底能够直接传送门去看node
可是惟一想要强调的是:初看本题可能会像我同样认为是点权+边权处理而后直接跑最短路...然鹅并非这样c++
我觉得的点权实际上是通过该城市的费用,是最终的答案算法
我觉得的边权实际上是通过该条边的流血量,是用来判断某一条从\(1\)到\(N\)的路径是否合法数组
什么意思?函数
就是要求咱们找到一条路,知足:spa
这条路上全部的流血量之和必须<\(b\)(给定的初始血量).net
这条路上通过的全部城市中最大费用值最小code
又是至关于同时维护两个东西,难搞htm
在以前有些题 中,咱们会选择“枚举其中一个再求解另一个的思路”
答案是确定的,可是面对这道题的数据范围:\(ci≤1000000000,fi≤1000000000\)
对了,那就是二分答案
咱们二分最大费用值最小,而后去\(check\)一下当前二分的答案是否合法:便是否有路径可以从\(1\)到\(N\)且路径上城市花费值≤当前的答案
咱们能够开另一个数组\(C'\)代替原来的城市费用数组\(C\)啊!而后直接对\(C'\)进行\(sort\),那咱们就能够对\(C'\)这个有序数列进行二分了!
sort(cc+1,cc+1+n); //变成有序序列 ans=cc[n]; l=1;r=n; while(l<=r) { //注意一下这里二分的是下标并非直接的值 long long mid=(l+r)>>1; if(check(cc[mid])==true) { ans=cc[mid]; r=mid-1; } else l=mid+1; } printf("%lld",ans);
inline bool check(long long x) { for(register int i=1;i<=n;i++) flag[i]=0; //记得清空! for(register int i=1;i<=n;i++) { if(c[i]>x) flag[i]=1; //全部大于当前答案的城市都不能走 } dijkstra(); if(dis[n]==1000000000+1||dis[n]>=b) return false; return true; }
#include <bits/stdc++.h> using namespace std; long long b,w,r,ans,l,c[5100005],cc[5100005]; int n,m,u,v,tot,dis[5100005],vis[5100005],flag[5100005]; int head[5100005]; priority_queue<pair<int,int> > shan; struct node { int to,net; long long val; } e[5100005]; inline void add(int u,int v,int w) { e[++tot].to=v; e[tot].val=w; e[tot].net=head[u]; head[u]=tot; } inline void dijkstra() { for(register int i=1;i<=n;i++) { vis[i]=0; dis[i]=1000000000+1; } dis[1]=0; shan.push(make_pair(0,1)); while(!shan.empty()) { int x=shan.top().second; shan.pop(); if(vis[x]) continue; vis[x]=1; for(register int i=head[x];i;i=e[i].net) { int v=e[i].to; if(dis[v]>dis[x]+e[i].val&&flag[x]==0&&flag[v]==0) { dis[v]=dis[x]+e[i].val; shan.push(make_pair(-dis[v],v)); } } } } inline bool check(long long x) { for(register int i=1;i<=n;i++) flag[i]=0; for(register int i=1;i<=n;i++) { if(c[i]>x) flag[i]=1; } dijkstra(); if(dis[n]==1000000000+1||dis[n]>=b) return false; return true; } int main() { scanf("%d%d%lld",&n,&m,&b); for(register int i=1;i<=n;i++) { scanf("%lld",&c[i]); cc[i]=c[i]; } for(register int i=1;i<=m;i++) { scanf("%d%d%lld",&u,&v,&w); add(u,v,w); add(v,u,w); } dijkstra(); if(dis[n]==1000000000+1||dis[n]>=b) { puts("AFK"); return 0; } sort(cc+1,cc+1+n); ans=cc[n]; l=1;r=n; while(l<=r) { long long mid=(l+r)>>1; if(check(cc[mid])==true) { ans=cc[mid]; r=mid-1; } else l=mid+1; } printf("%lld",ans); return 0; }