洛谷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;
}

猜你喜欢

转载自www.cnblogs.com/linxif2008/p/10091148.html
今日推荐