思路:二分+最短路
提交:1次
题解:
二分最后的答案。
$ck()$: 对于每次的答案$md$跑$s,t$的最短路,但是不让$c[u]>md$的点去松弛别的边,即保证最短路不经过这个点。最后$returnspace dis(s,t)<=$油箱容量
代码:
#include<cstdio> #include<iostream> #include<queue> #include<cstring> #define R register int using namespace std; //你弱,有什么资格休息 #define ull unsigned long long #define ll long long #define pause (for(R i=1;i<=10000000000;++i)) #define In freopen("NOIPAK++.in","r",stdin) #define Out freopen("out.out","w",stdout) namespace Fread { static char B[1<<15],*S=B,*D=B; #ifndef JACK #define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++) #endif inline int g() { R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix; if(ch==EOF) return EOF; do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix; } inline bool isempty(const char& ch) {return (ch<=36||ch>=127);} inline void gs(char* s) { register char ch; while(isempty(ch=getchar())); do *s++=ch; while(!isempty(ch=getchar())); } } using Fread::g; using Fread::gs; namespace Luitaryi { #define pii pair<ll,int> #define mp make_pair const int N=1e+4+10,M=1e+5+10; int n,m,s,t,W,mx,cnt; int vr[M],nxt[M],w[M],fir[N],c[N]; ll d[N]; bool vis[N]; inline void add(int u,int v,int ww) {vr[++cnt]=v,nxt[cnt]=fir[u],w[cnt]=ww,fir[u]=cnt;} priority_queue<pii > q; inline bool ck(int x) { q.push(mp(0,s)); if(c[s]>x) return false; memset(d,0x3f,sizeof(d)),memset(vis,0,sizeof(vis)); d[s]=0; while(q.size()) { R u=q.top().second; q.pop(); if(vis[u]) continue; vis[u]=true; if(c[u]>x) continue; for(R i=fir[u];i;i=nxt[i]) { R v=vr[i]; if(d[v]>d[u]+w[i]) { d[v]=d[u]+w[i]; q.push(mp(-d[v],v)); } } } return d[t]<=W; } inline void main() { n=g(),m=g(),s=g(),t=g(),W=g(); for(R i=1;i<=n;++i) c[i]=g(),mx=max(c[i],mx); for(R i=1,u,v,w;i<=m;++i) u=g(),v=g(),w=g(),add(u,v,w),add(v,u,w); R l=max(c[s],c[t]),r=mx+1; while(l<r) { R md=l+r>>1; if(ck(md)) r=md; else l=md+1; } printf("%d ",l==mx+1?-1:l); } } signed main() { Luitaryi::main(); return 0; }
2019.07.15