洛谷 P1462 通往奥格瑞玛的道路——二分+spfa

上一波链接 https://www.luogu.org/problem/P1462

这道题我们考虑二分答案 然后每次跑一次spfa判断是否能够到达n点 

tips:在不考虑负权边的前提下我们写最短路最好考虑dijstra 因为spfa的复杂度最差是 VE

随机数据下两种算法速度差不多 但spfa会被特殊数据卡掉 当然若有负权边就只能写spfa了

#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;
}
View Code

猜你喜欢

转载自www.cnblogs.com/yourinA/p/11709912.html
今日推荐