洛谷1462通往奥格瑞玛的道路

Posted Narh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷1462通往奥格瑞玛的道路相关的知识,希望对你有一定的参考价值。

题目:https://www.luogu.org/problemnew/show/P1462

二分答案。

为什么djkstra不行,spfa可以?

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define ll long long
using namespace std;
const int N=1e5+5,M=5e5+5;
int n,m,head[N],xnt;
ll b,v[N],l,r,ans=-1,dis[N];
bool vis[N];
struct Edge{
    int next,to;ll w,c;
    Edge(int n=0,int t=0,ll w=0,ll c=0):next(n),to(t),w(w),c(c) {}
}edge[M<<1];
struct Node{
    int bh;ll c;
    Node(int b=0,ll c=0):bh(b),c(c) {}
    bool operator <(const Node &a)const
    {return c<a.c;}
};
void add(int x,int y,ll z)
{
    edge[++xnt]=Edge(head[x],y,z,v[y]);head[x]=xnt;
    edge[++xnt]=Edge(head[y],x,z,v[x]);head[y]=xnt;
}
bool dj(ll mid)
{
    printf("mid=%lld\n",mid);
    memset(dis,11,sizeof dis);
    memset(vis,0,sizeof vis);
    queue<Node> q;
    dis[1]=0;q.push(Node(1,0));
    while(q.size())
    {
        int k=q.front().bh;q.pop();
        while(q.size()&&vis[k])k=q.front().bh,q.pop();
        if(vis[k])break;vis[k]=1;
        for(int i=head[k],v;i;i=edge[i].next)
        {
//            if(edge[i].c<=mid)printf("1");
//            if(dis[v=edge[i].to]>dis[k]+edge[i].w)printf("2");
//            if(dis[k]+edge[i].w<=b)printf("3");printf("v=%d\n",v);
            if(edge[i].c<=mid&&dis[v=edge[i].to]>dis[k]+edge[i].w&&dis[k]+edge[i].w<=b)
            {dis[v]=dis[k]+edge[i].w;q.push(Node(v,dis[v]));if(v==n)return true;}
        }
    }
    return false;
}
bool spfa(ll mid)
{
    memset(dis,11,sizeof dis);
    memset(vis,0,sizeof vis);
    queue<int> q;
    q.push(1);dis[1]=0;vis[1]=1;
    while(q.size())
    {
        int k=q.front();q.pop();vis[k]=0;
        for(int i=head[k],v;i;i=edge[i].next)
        if(edge[i].c<=mid&&dis[v=edge[i].to]>dis[k]+edge[i].w&&dis[k]+edge[i].w<=b)
            {
                dis[v]=dis[k]+edge[i].w;
                if(!vis[v])vis[v]=1,q.push(v);
                if(v==n)return true;
            }
    }
    return false;
}
int main()
{
//    freopen("洛谷1462#8.in","r",stdin);
    scanf("%d%d%lld",&n,&m,&b);int x,y;ll z;
    for(int i=1;i<=n;i++)scanf("%lld",&v[i]),r=max(r,v[i]);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%lld",&x,&y,&z);
        add(x,y,z);
    }
//    printf("l=%lld r=%lld\n",l,r);
    while(l<=r)
    {
        ll mid=((l+r)>>1);
        if(spfa(mid))ans=mid,r=mid-1;
        else l=mid+1;
    }
    if(ans==-1)printf("AFK");
    else printf("%lld",ans);
    return 0;
}

 

以上是关于洛谷1462通往奥格瑞玛的道路的主要内容,如果未能解决你的问题,请参考以下文章

洛谷P1462通往奥格瑞玛的道路——二分答案最短路

AC日记——通往奥格瑞玛的道路 洛谷 P1462

洛谷—— P1462 通往奥格瑞玛的道路

通往奥格瑞玛的道路(洛谷 1462)

洛谷P1462 通往奥格瑞玛的道路 二分答案+最短路SPFA

洛谷 P1462 通往奥格瑞玛的道路