1. 程式人生 > >洛谷P1462 通往奧格瑞瑪的道路

洛谷P1462 通往奧格瑞瑪的道路

洛谷P1462 通往奧格瑞瑪的道路

題目背景

在艾澤拉斯大陸上有一位名叫歪嘴哦的神奇術士,他是部落的中堅力量
有一天他醒來後發現自己居然到了聯盟的主城暴風城
在被眾多聯盟的士兵攻擊後,他決定逃回自己的家鄉奧格瑞瑪

題目描述

在艾澤拉斯,有\(n\)個城市。編號為\(1,2,3,...,n\)
城市之間有\(m\)條雙向的公路,連線著兩個城市,從某個城市到另一個城市,會遭到聯盟的攻擊,進而損失一定的血量。
每次經過一個城市,都會被收取一定的過路費(包括起點和終點)。路上並沒有收費站。
假設1為暴風城,\(n\)為奧格瑞瑪,而他的血量最多為\(b\),出發時他的血量是滿的。
歪嘴哦不希望花很多錢,他想知道,在可以到達奧格瑞瑪的情況下,他所經過的所有城市中最多的一次收取的費用的最小值是多少。

輸入輸出格式

輸入格式:

第一行3個正整數,\(n\)\(m\)\(b\)。分別表示有\(n\)個城市,\(m\)條公路,歪嘴哦的血量為\(b\)
接下來有\(n\)行,每行1個正整數,\(f_i\)。表示經過城市\(i\),需要交費\(f_i\)元。
再接下來有\(m\)行,每行3個正整數,\(a_i\)\(b_i\)\(c_i\)\((1 \leq a_i,b_i \leq n)\)。表示城市\(a_i\)和城市\(b_i\)之間有一條公路,如果從城市\(a_i\)到城市\(b_i\),或者從城市\(b_i\)到城市\(a_i\),會損失\(c_i\)的血量。

輸出格式:

僅一個整數,表示歪嘴哦交費最多的一次的最小值。
如果他無法到達奧格瑞瑪,輸出AFK

思路

二分答案
二分交費的最小值\(k\)
然後判斷是否可行的方法是:在圖中刪去所有費用大於\(k\)的點,再跑最短路,如果最短路的值大於歪嘴哦的血量,那就不可行,否則可行

CODE

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define MAXN 10010
#define MAXM 200010
struct Node{
    int u,v,w;
    Node(){}
    Node(int u,int v,int w):u(u),v(v),w(w){}
}p[MAXM];
struct R{
    int id,dis;
    R(){}
    R(int id,int dis):id(id),dis(dis){}
    bool operator < (const R &a) const{
        return dis>a.dis;
    }
}tmp;
int head[MAXN],Next[MAXM],dis[MAXN],cost[MAXN];
priority_queue<R> mque;
bool vis[MAXN];
int i,j,k,m,n,u,v,w,tot,l,r,mid,ans,b,upborder;
bool flag;
void addNode(int u,int v,int w){
    p[++tot]=Node(u,v,w);
    Next[tot]=head[u],head[u]=tot;
    p[++tot]=Node(v,u,w);
    Next[tot]=head[v],head[v]=tot;
}
bool dijkstra(int src,int goal){
    if(cost[src]>mid) return false;
    while(!mque.empty()) mque.pop();
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    dis[src]=0;
    mque.push(R(src,0));
    while(!mque.empty()){
        tmp=mque.top(); mque.pop();
        if(vis[tmp.id]) continue;
        vis[tmp.id]=true;
        for(register int i=head[tmp.id];i+1;i=Next[i]){
            if(cost[p[i].v]<=mid&&dis[p[i].u]+p[i].w<dis[p[i].v]){
                dis[p[i].v]=dis[p[i].u]+p[i].w;
                mque.push(R(p[i].v,dis[p[i].v]));
            }
        }
    }
    if(dis[goal]<b) return true;
    return false;
}
void solve(){
    l=0,r=1000000000;
    flag=false;
    while(l<r){
        mid=(l+r)>>1;
        if(dijkstra(1,n)){
            r=mid;
            flag=true;
        }else{
            l=mid+1;
        }
    }
}
int main(){
    scanf("%d%d%d",&n,&m,&b);
    memset(head,-1,sizeof(head));
    tot=-1; upborder=0;
    for(i=1;i<=n;i++){
        scanf("%d",cost+i);
    }
    for(i=1;i<=m;i++){
        scanf("%d%d%d",&u,&v,&w);
        addNode(u,v,w);
        upborder=max(upborder,w);
    }
    solve();
    if(flag){
        printf("%d\n",l);
    }else{
        printf("AFK\n");
    }
    return 0;
}