上一波链接 https://www.luogu.org/problem/P1462
这道题我们考虑二分答案 然后每次跑一次spfa判断是否能够到达n点
tips:在不考虑负权边的前提下我们写最短路最好考虑dijstra 因为spfa的复杂度最差是 VE
随机数据下两种算法速度差不多 但spfa会被特殊数据卡掉 当然若有负权边就只能写spfa了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<cmath> #define LL long long using namespace std; const int M=1e5+7; const LL inf=1e15; LL read(){ LL ans=0,f=1,c=getchar(); while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();} return ans*f; } LL n,m,T,s[M]; LL first[M],cnt=0; struct node{LL to,next,w;}e[2*M]; void ins(LL x,LL y,LL w){e[++cnt]=(node){y,first[x],w}; first[x]=cnt;} LL dis[M],L,R,vis[M]; queue<int>q; int pd(LL mx){ for(int i=1;i<=n;i++) dis[i]=inf,vis[i]=0; dis[1]=0; vis[1]=1; q.push(1); while(!q.empty()){ int x=q.front(); q.pop(); for(int i=first[x];i;i=e[i].next){ int now=e[i].to; if(s[now]>mx) continue; if(dis[now]>dis[x]+e[i].w){ dis[now]=dis[x]+e[i].w; if(!vis[now]) vis[now]=1,q.push(now); } } vis[x]=0; } //printf("qwq%lld %lld\n",mx,dis[n]); if(dis[n]>T) return 0; return 1; } int main(){ int x,y,w; n=read(); m=read(); T=read(); for(int i=1;i<=n;i++) s[i]=read(),R=max(R,s[i]); for(int i=1;i<=m;i++) x=read(),y=read(),w=read(),ins(x,y,w),ins(y,x,w); if(!pd(R)){puts("AFK"); return 0;} L=1; R++; while(L<R){ LL mid=L+R>>1; if(pd(mid)) R=mid; else L=mid+1; } printf("%lld\n",R); return 0; }