• 【Luogu】P1462通往奥格瑞玛的道路(二分答案+SPFA)


      题目链接

      导致我WA十几遍的原因居然是最大值不够大……以后再也不相信memset(dis,127/3,sizeof(dis))了。

      此题先将花费排序,然后二分最大花费,spfa判断解是否可行。spfa的时候遇到一个大于当前二分的花费的点就跳过。如果起点的点权超过了这个花费,或者最后到达n时的最短路径超过了歪嘴哦的血量,则当前解不可用,l=mid+1.否则记录当前答案,r=mid-1。

      代码如下

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    struct Edge{
        int next,to,dis;
    }edge[1000000];
    int head[1000000],num;
    int dis[200000];
    inline void add(int from,int to,int dis){
        edge[++num]=(Edge){head[from],to,dis};
        head[from]=num;
    }
    
    int que[100000];
    int cost[1000000];
    
    int f[1000000],h,t=1;
    bool vis[200000];
    long long ans=-1;
    int main(){
        int n=read(),m=read(),Max=read();
        for(int i=1;i<=n;++i){
            que[i]=read();
            cost[i]=que[i];
        }
        sort(que+1,que+n+1);
        for(int i=1;i<=m;++i){
            int from=read(),to=read(),dst=read();
            add(from,to,dst);
            add(to,from,dst);
        }
        int l=1,r=n;
        while(l<=r){
            int mid=(l+r)>>1;
            for(int i=1;i<=n;++i)    dis[i]=1000000000;
            memset(vis,0,sizeof(vis));
            int limit=que[mid];
            f[1]=1;h=0;t=1;dis[1]=0;
            while(h++<t){
                vis[f[h]]=0;
                for(int i=head[f[h]];i;i=edge[i].next){
                    if(cost[edge[i].to]>limit)    continue;
                    if(dis[f[h]]+edge[i].dis<dis[edge[i].to]){
                        dis[edge[i].to]=dis[f[h]]+edge[i].dis;
                        if(!vis[edge[i].to]){
                            vis[edge[i].to]=1;
                            f[++t]=edge[i].to;
                        }
                    }
                }
            }
            if(dis[n]>=Max||cost[1]>limit)    l=mid+1;
            else{
                ans=que[mid];
                r=mid-1;
            }
        }
        if(ans==-1)    printf("AFK");
        else        printf("%lld",ans);
        return 0;
    }
  • 相关阅读:
    Sql inner join
    转:MySQL 的show processlist
    session cookie
    集群和分布式
    设计模式
    Web性能优化——缓存
    关于 java 里面的路径
    1分钟看懂log4j 配置自己想要的日志信息
    spring @bean 的理解
    如何用iptables实现NAT(转)
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/7521793.html
Copyright © 2020-2023  润新知