[題解](最短路/二分)luogu_P1462通往奧格瑞瑪的道路

看到最大的最小值應該想到二分答案,這樣就解決了最小點權的問題,判血量就很好說,直接比較就行,

一個點是二分點權數組,複製一份然後排序,二分下標,速度較快

這麼簡單的題我竟然寫了這麼長時間

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
using namespace std;
const int maxn=10005;
const int maxm=50005;
int n,m,b,w[maxn],ans,f[maxn];
int head[maxn],cnt;
struct node{
    int v,w,nxt;
}e[maxm*2];
ll d[maxn];bool v[maxn];
void add(int u,int v,int w){e[++cnt].v=v;e[cnt].w=w;e[cnt].nxt=head[u];head[u]=cnt;}
bool spfa(int top){
    memset(d,0x3f,sizeof(d));
    memset(v,0,sizeof(v));
    queue<int>q;
    d[1]=0;v[1]=1;q.push(1);
    while(!q.empty()){
        int x=q.front();q.pop();v[x]=0;
        for(int i=head[x];i;i=e[i].nxt){
            int y=e[i].v,z=e[i].w;
            if(d[y]>d[x]+z && w[y]<=top){
                d[y]=d[x]+z;
                if(!v[y])q.push(y),v[y]=1;
            }
        }
    }
    if(d[n]<=b)return 1;
    else return 0;
}
int main()
{
    scanf("%d%d%d",&n,&m,&b);
    for(int i=1;i<=n;i++)scanf("%d",&w[i]),f[i]=w[i];
    for(int i=1,x,y,z;i<=m;i++){
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);add(y,x,z);
    }
    sort(f+1,f+1+n);
    if(!spfa(0x7fffffff)){printf("AFK\n");return 0;}//無限制都不能到達,血量不夠 
    int l=1,r=n;//二分f數組,比較快 
    while(l<=r){
        int mid=(l+r)>>1;
        if(spfa(f[mid]))r=mid-1,ans=f[mid];
        else l=mid+1;
    }
    printf("%d\n",ans);
}

 

posted @ 2019-04-12 20:35  羊肉汤泡煎饼  阅读(121)  评论(0编辑  收藏  举报