P1462 通往奥格瑞玛的道路

原题链接

分析

本题和Acw中的通信线路,几乎相同。

在通信线路中,我们需要求,从起点到终点的路径中,第k+1大的边权的最小值

而在本题中,我们要求得是,从起点到终点的路径中,最大点权的最小值

那思路就一下清晰起来了,我们可以去二分答案,枚举这个最大值。

对于枚举的每一个值,我们看一下,对于这个值来说,能否顺利走到最终点。

Ac_Code

//求出所有合法路径中点的最大值
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N = 1e4 + 10,M = 1e5 + 10,INF = 0x3f3f3f3f;
int h[N],e[M],ne[M],w[M],idx;
int v[N],dist[N],vv[N];
bool st[N];
int n,m,B;

void add(int a,int b,int c)
{
    e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}

bool spfa(int mid)
{
    memset(st,0,sizeof st);
    memset(dist,0x3f,sizeof dist);
    queue<int> q;
    q.push(1);
    st[1]=1;
    dist[1]=0;
    while(q.size())
    {
        auto t = q.front();
        q.pop();
        if(v[t]>mid) return 0;
        st[t]=0;
        for(int i=h[t];~i;i=ne[i])
        {
            int j = e[i];
            if(dist[j]>dist[t]+w[i]&&v[j]<=mid)
            {
                dist[j]=dist[t]+w[i];
                if(!st[j])
                {
                    st[j]=1;
                    q.push(j);
                }                
            }
        }
    }
    if(dist[n]<=B) return 1;
    return 0;
}

int main()
{
    cin>>n>>m>>B;
    memset(h,-1,sizeof h);
    for(int i=1;i<=n;i++) cin>>v[i],vv[i]=v[i];
    while(m--)
    {
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c),add(b,a,c);
    }
    sort(vv+1,vv+n+1);
    if(!spfa(vv[n])){
        printf("AFK\n");return 0;}
    int l = 1,r = n,ans = vv[n];
    while(l<r){
        int mid = l + r>> 1;
        if(spfa(vv[mid])) 
        {
            ans = vv[mid];
            r=mid;
        }
        else l = mid + 1;
    }
    cout<<ans<<endl;
    return 0;
}
posted @ 2021-11-15 09:27  艾特玖  阅读(53)  评论(0)    收藏  举报