P1462 通往奥格瑞玛的道路 最短路+二分

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/JiangHxin/article/details/101287733

本人也是初学最短路,欢迎交流。

关于dijkstra

P1462 通往奥格瑞玛的道路

原题链接:传送门

思路:

  1. 题目有点类似与求最短路的最大边权的最小值,不过这里求的是消耗最大费用的最小值,不难想到二分,这里的边权作为生命值用来判断当前费用能否从联盟中心活着到家。
  2. 二分答案+dij , 写这道题的时候不小心把前向星的head[u]写成head[i]卡了一个小时,吸取这次教训。

    代码如下:
#include<bits/stdc++.h>
using namespace std;
const int emmm=1000000005;
const int manx=1e4+5;
const int mamx=1e5+5;
int head[manx],d[manx],c[manx]; //head[]和d[] vis[]作为常规dij必需品 c[]这里存每个城市的消耗费用
bool vis[manx];
priority_queue<pair<int ,int > >q;
int n,m,s,k=0,ans=0;
struct node{
    int v,next,w;
}a[mamx];
void add(int u,int v, int w)
{
    a[++k].next=head[u];
    head[u]=k;
    a[k].w=w;
    a[k].v=v;
}
bool dij(int x) //最短路判断血量是否为0
{
    if(x<c[1]) return 0; //如果连起点的城市都出不去肯定不行
    for(int i=1;i<=n;i++) d[i]=1e9,vis[i]=0; //d[i]初始化一定要够大,一开始初始化为0x3f也卡了一会儿
    q.push(make_pair(0,1)); //下面是常规的dij操作
    d[1]=0;
    while(q.size())
    {
        int u=q.top().second;
        q.pop();
        if(vis[u]) continue;
        vis[u]=1;
        for(int i=head[u];i;i=a[i].next)
        {
            int v=a[i].v,w=a[i].w;
            if(d[v]>d[u]+w && x>=c[v] &&!vis[v] ) d[v]=d[u]+w,q.push(make_pair(-d[v],v));
        }
    }
    if(d[n]<s) return 1;
    else return 0;
}
int main()
{
    scanf("%d%d%d",&n,&m,&s);
    for(int i=1;i<=n;i++) scanf("%d",&c[i]);
    for(int i=1;i<=m;i++)
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);  //注意无向图 要建两条边
        add(v,u,w);
    }
    if(!dij(emmm)){ //首先判断最大费用 如果不行的话比他小的也不行
        cout<<"AFK"<<endl;
        return 0;
    }
    int l=1,r=emmm;  //二分操作,过段时间会整理总结一下二分
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(dij(mid)) r=mid-1;
        else l=mid+1;
    }
    printf("%d",l);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/JiangHxin/article/details/101287733
今日推荐