洛谷 P1462 通往奥格瑞玛的道路(二分答案+最短路)

题目大意:n个点,m条边,开始血量为b,从1出发,要走到n,每条边有个扣血量,每个点有个价值,求在血量不为负走到第n个点时,走过的路径点权最大值最小.

最大值最小,很容易想到二分答案,由于血量是边权,我们可以跑最短路来保证他能走到终点,我们二分最大点权,在跑最短路时如果跑到比当前二分到的最大点权还大的点,那么这个点是不合法的不能更新,跑完判断血量的大小.

要注意的是点权是无序的,我们先排序一遍让它单调递增,写个二分+Dij堆优化搞定。

还要注意各种long long==

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <cmath>
  6 #include <queue>
  7 #include <map>
  8 #define ll long long
  9 #define out(a) printf("%lld",a)
 10 #define writeln printf("\n")
 11 const int N=1e5+50;
 12 const int mod=1e9+7;
 13 using namespace std;
 14 int n,m;
 15 ll b,z,ans=0;
 16 int l,r,mid,tot=0;
 17 int x,y;
 18 int head[N];
 19 ll dis[N],f[N],num[N];
 20 bool vis[N],flag;
 21 struct node
 22 {
 23     int to,next;
 24     ll blood;
 25 }edge[N];
 26 struct dist
 27 {
 28     ll h;int id;
 29     bool operator<(const dist&a)const{
 30       return h>a.h;
 31     }
 32 };
 33 priority_queue<dist>q;
 34 int read()
 35 {
 36     int s=0,t=1; char c;
 37     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
 38     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
 39     return s*t;
 40 }
 41 ll readl()
 42 {
 43     ll s=0,t=1; char c;
 44     while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();}
 45     while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();}
 46     return s*t;
 47 }
 48 void add(int x,int y,ll z)
 49 {
 50     edge[++tot].to=y;
 51     edge[tot].blood=z;
 52     edge[tot].next=head[x];
 53     head[x]=tot;
 54 }
 55 bool check(ll mid)
 56 {
 57     dist p; int x;
 58     memset(dis,127,sizeof(dis));
 59     dis[1]=0; 
 60     memset(vis,false,sizeof(vis));
 61     p.h=0; p.id=1;
 62     q.push(p);
 63     while (!q.empty()){
 64       p=q.top(); q.pop();
 65       x=p.id;
 66       if (!vis[x]){
 67         vis[x]=true;
 68       for (int i=head[x];i;i=edge[i].next){
 69           y=edge[i].to; z=edge[i].blood;
 70           if (f[y]>mid) {
 71            continue;
 72         }
 73           if (dis[y]>dis[x]+z) {
 74             dis[y]=dis[x]+z;
 75             p.h=dis[y]; p.id=y;
 76             q.push(p);
 77         }
 78       }
 79       }
 80     }
 81     return dis[n]>b?false:true;
 82 }
 83 int main()
 84 {
 85     n=read(); m=read(); b=readl();
 86     for (int i=1;i<=n;i++)
 87       f[i]=readl(),num[i]=f[i];
 88     for (int i=1;i<=m;i++){
 89       x=read(),y=read(),z=readl();
 90       add(x,y,z); add(y,x,z);
 91     }    
 92     l=1; r=n; flag=false;
 93     sort(num+1,num+n+1);
 94     while (l<=r){
 95       mid=(l+r)>>1;
 96       if (check(num[mid])) {
 97         r=mid-1;
 98           ans=num[mid];
 99           flag=true;
100       }
101       else l=mid+1;
102     }
103     if (flag) out(ans);
104     else puts("AFK");
105     return 0;
106 }
107       
View Code

 

posted @ 2018-08-05 16:41  Kaleidoscope233  阅读(194)  评论(0编辑  收藏  举报