洛谷P1462 通往奥格瑞玛的道路 二分答案,dijkstra求最短路,堆优化

将每个城市的所需过路费放在答案数组中,排序,找到起点与终点最大过路费的位置,作为二分的左界,所有城市中最大的过路费作为二分的右界。每次选一个上限花费,高于这个消费的城市就不能选择,dijkstra找耗血最少的路线即最短路,看以这个花费作为上限花费,能不能血量高于0走到终点,如果能r=mid,降低上限消费,如果不能,l=mid+1,提高上限消费,下贴代码。

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e4+5;
const int maxm=1e5+5;
const int inf=1e9+7;
struct que
{
    int key,value;
    friend bool operator < (que a,que b)
    {
        return a.value > b.value;
    }
};
priority_queue<que>q;
struct node
{
    int to,next,len;
}p[maxm];
int head[maxn];
int a[maxn],b[maxn];
int vertex[maxn];
bool vis[maxn];
int n,m,c;
int cnt,ans;
void add(int x,int y,int w)
{
    p[++cnt].next=head[x];
    p[cnt].to=y;
    p[cnt].len=w;
    head[x]=cnt;
}
bool check(int top)
{
    if(top<a[1])
    return false;
    for(int i=2;i<=n;i++)
    vertex[i]=inf,vis[i]=false;
    vis[1]=true;
    for(int i=head[1];i;i=p[i].next)
    {
        int v=p[i].to;
        //cout<<v<<endl;
        int cost=p[i].len;
        //cout<<cost<<endl;
        if(vertex[v]>cost&&a[v]<=top)
        {
            //cout<<a[v]<<endl;
            vertex[v]=cost;
            q.push({v,cost});
        }
    }
    while(!q.empty())
    {
        que temp=q.top();
        q.pop();
        if(vis[temp.key])
        continue;
        vis[temp.key]=true;
        for(int i=head[temp.key];i;i=p[i].next)
        {
            int v=p[i].to;
            int cost=p[i].len;
            if(a[v]<=top&&(vertex[v]>(temp.value+cost))&&!vis[v])
            {
                vertex[v]=temp.value+cost;
                q.push({v,vertex[v]});
            }
        }
    }
    if(c-vertex[n]>0)
    return true;
    else
    return false;
}
int main()
{
    scanf("%d %d %d",&n,&m,&c);
    int l,r,mid;
    for(int i=1;i<=n;i++)
    scanf("%d",&a[i]),b[i]=a[i];
    int t1=a[1],t2=a[n];
    sort(b+1,b+1+n);
    int Ma=-1;
    for(int i=1;i<=n;i++)
    if(b[i]==t1||b[i]==t2)
    {
        if(Ma<b[i])
        Ma=b[i],l=i;
    }
    r=n;
    for(int i=1;i<=m;i++)
    {
        int x,y,w;
        scanf("%d %d %d",&x,&y,&w);
        add(x,y,w);
        add(y,x,w);
    }
    //cout<<b[n]<<endl;
    //check(b[n]);
    //printf("%d\n",vertex[n]);
    if(!check(b[n]))
    {
        puts("AFK");
        return 0;
    }
    ans=b[n];
    while(l<r)
    {
        mid=(l+r)>>1;
        int top=b[mid];
        if(check(top))
        r=mid,ans=top;
        else
        l=mid+1;
    }
    printf("%d\n",ans);
    return 0;
}
发布了3 篇原创文章 · 获赞 2 · 访问量 15

猜你喜欢

转载自blog.csdn.net/weixin_44491423/article/details/104442855
今日推荐