通往奥格瑞玛的道路

题目背景
在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士,他是部落的中坚力量
有一天他醒来后发现自己居然到了联盟的主城暴风城
在被众多联盟的士兵攻击后,他决定逃回自己的家乡奥格瑞玛
题目描述
在艾泽拉斯,有n个城市。编号为1,2,3,...,n。
城市之间有m条双向的公路,连接着两个城市,从某个城市到另一个城市,会遭到联盟的攻击,进而损失一定的血量。
每次经过一个城市,都会被收取一定的过路费(包括起点和终点)。路上并没有收费站。
假设1为暴风城,n为奥格瑞玛,而他的血量最多为b,出发时他的血量是满的。
歪嘴哦不希望花很多钱,他想知道,在可以到达奥格瑞玛的情况下,他所经过的所有城市中最多的一次收取的费用的最小值是多少。
输入输出格式
输入格式:
第一行3个正整数,n,m,b。分别表示有n个城市,m条公路,歪嘴哦的血量为b。
接下来有n行,每行1个正整数,fi。表示经过城市i,需要交费fi元。
再接下来有m行,每行3个正整数,ai,bi,ci(1<=ai,bi<=n)。表示城市ai和城市bi之间有一条公路,如果从城市ai到城市bi,或者从城市bi到城市ai,会损失ci的血量。
输出格式:
仅一个整数,表示歪嘴哦交费最多的一次的最小值。
如果他无法到达奥格瑞玛,输出AFK。

#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
using namespace std;

typedef long long ll;
const int maxn = 200000;

int n,m,b;

struct edge{
  int t,w,next;
}e[maxn];
int head[maxn],d[maxn];
int cnt;
int inq[maxn];
void insert(int s,int t,int w)
{
  e[++cnt].t = t;
  e[cnt].w = w;
  e[cnt].next = head[s];
  head[s] = cnt;
}
int p[maxn];


bool check(int zat){
  queue<int> Q;
  Q.push(1);
  memset(d,0x3f,sizeof(d));
  memset(inq,0,sizeof(inq));
  inq[1] = 1;
  d[1] = 0;
  while(!Q.empty()){
    int x = Q.front();Q.pop();
    inq[x] = 0;
    for(int i = head[x];i != 0;i = e[i].next){
      if(p[e[i].t] <= zat){
        if(d[e[i].t] > d[x] + e[i].w){
          d[e[i].t] = d[x] + e[i].w;
          if(!inq[e[i].t]){
            Q.push(e[i].t);
            inq[e[i].t] = 1;
          }
        }
      }      
    }
  }
  return (d[n] < b);
}

int main()
{
  scanf("%d%d%d",&n,&m,&b);
  for(int i = 1;i <= n;i++) scanf("%d",&p[i]);
  for(int i = 1;i <= m;i++){
    int s,t,w;
    scanf("%d%d%d",&s,&t,&w);
    insert(s,t,w);
    insert(t,s,w);
  }
  
  int L = p[1];int R = 1e9;
  while(R>L){
    int m = (R+L)/2;
    if(check(m)){
      R = m;    
    }else L = m+1;
  }
  if(L == 1e9) printf("AFK\n");
  else printf("%d",L);
  return 0;
}
posted @ 2017-11-02 11:34  rsqppp  阅读(76)  评论(0)    收藏  举报