P1462 通往奥格瑞玛的道路

题意:给出一个图,让我们从1走到n;

  每一条边有一个权值(伤害值),每一个顶点也有一个权值(收费值);

  从1走到n的某路径的答案为,这些路径中的最大值; 假如生命耗尽,也无法走到终点,

  现在让我们找出这样一条路径,求最小的花费值;

思路:我们通过二分便可以解决;

   二分对象为花费值,然后每一次按这个花费值去跑SPFA算出在这花费值的情况下最小的伤害  

   假如遇到比该花费值大的点,就跳过;

   然后该最小伤害大于本身最大生命值的话,则不满足,反之满足

   但是,当我们将数据范围定义到题目给出的范围的时候,大致为:(1,1e9)

   这样做会超时,然后我们换了一种跑范围的方法,将范围降到了(1,1e4)

   很显然,我们枚举的花费值最后的答案,如果满足的话,肯定是等于这些花费值中的其中一个

   所以我们只需要跑花费值这个数组就可以了

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e4+10;
 4 const int inf=0x3f3f3f3f;
 5 int money[maxn];
 6 int n,m,health;
 7 int dis[maxn];
 8 int vis[maxn];
 9 int sto[maxn];
10 struct node
11 {
12     int w,v,nxt;
13 }G[100010]; int head[100010];int num;
14 void add(int u,int v,int w)
15 {
16     G[++num].v=v;G[num].w=w;G[num].nxt=head[u];head[u]=num;
17 }
18 void SPFA(int mid)
19 {
20     if(money[1]>mid) return;
21     queue<int>q;
22     q.push(1);
23     dis[1]=0;
24     vis[1]=1;
25     while(!q.empty()){
26         int u=q.front();
27         q.pop();
28         vis[u]=0;
29         for(int i=head[u];i;i=G[i].nxt){
30             int v=G[i].v,w=G[i].w;
31             if(money[v]>mid) continue;
32             if(dis[v]>dis[u]+w){
33                 dis[v]=dis[u]+w;
34                 if(!vis[v]){
35                     vis[v]=1;
36                     q.push(v);
37                 }
38             }
39         }
40     }
41 }
42 int check(int mid)
43 {
44     memset(dis,inf,sizeof(dis));
45     memset(vis,0,sizeof(vis));
46     SPFA(mid);
47     if(dis[n]<=health) return 1;
48     else return 0;
49 }
50 int main()
51 {
52     scanf("%d%d%d",&n,&m,&health);
53     for(int i=1;i<=n;i++){
54         scanf("%d",&money[i]);
55         sto[i]=money[i];
56     }
57     for(int i=1;i<=m;i++){
58         int u,v,w;
59         scanf("%d%d%d",&u,&v,&w);
60         add(u,v,w);
61         add(v,u,w);
62     }
63     sort(sto+1,sto+1+n);
64     if(check(sto[n])==0){
65         printf("AFK\n");
66         return 0;
67     }
68     int L=1,R=n;
69     int ans;
70     while(L<=R){
71         int mid=L+R>>1;
72         if(check(sto[mid])){
73             ans=sto[mid];
74             R=mid-1;
75         }
76         else L=mid+1;
77     }
78     printf("%d\n",ans);
79     return 0;
80 }
View Code

 

posted @ 2020-04-15 11:56  古比  阅读(131)  评论(0编辑  收藏  举报