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