[Luogu1462]通往奥格瑞玛的道路

题目大意:
  一个n个点,m条边的图,每个边有一个边权,每个点也有一个点权。
  现在要找一条从1到n的路径,保证边权和不超过b的情况下,最大点权尽量小。
  问最大点权最小能是多少?

思路:
  二分答案,然后Dijkstra跑最短路判断可行性。
  假设二分到的最大点权为m,那么最短路中跑到点权>m的直接忽略,对于长度大于b的最短路也直接忽略。
  对点权离散化后二分会快不少。

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<vector>
 4 #include<algorithm>
 5 #include<functional>
 6 #include<ext/pb_ds/priority_queue.hpp>
 7 inline int getint() {
 8     register char ch;
 9     while(!isdigit(ch=getchar()));
10     register int x=ch^'0';
11     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
12     return x; 
13 }
14 const int inf=0x7fffffff;
15 const int N=10001;
16 int f[N],n,m,b;
17 struct Edge {
18     int to,w;
19 };
20 std::vector<Edge> e[N];
21 inline void add_edge(const int &u,const int &v,const int &w) {
22     e[u].push_back((Edge){v,w});
23     e[v].push_back((Edge){u,w});
24 }
25 int d[N];
26 struct Vertex {
27     int id,dis;
28     bool operator > (const Vertex &another) const {
29         return dis>another.dis;
30     }
31 };
32 __gnu_pbds::priority_queue<Vertex,std::greater<Vertex> > q;
33 __gnu_pbds::priority_queue<Vertex,std::greater<Vertex> >::point_iterator p[N];
34 inline void dijkstra(const int &m) {
35     p[1]=q.push((Vertex){1});
36     for(register int i=2;i<=n;i++) {
37         p[i]=q.push((Vertex){i,d[i]=b+1});
38     }
39     while(q.top().dis<=b) {
40         const int x=q.top().id;
41         for(register unsigned i=0;i<e[x].size();i++) {
42             const int &y=e[x][i].to;
43             if(f[y]>m) continue;
44             if(d[x]+e[x][i].w<d[y]) {
45                 q.modify(p[y],(Vertex){y,d[y]=d[x]+e[x][i].w});
46             }
47         }
48         q.modify(p[x],(Vertex){0,b+1});
49     }
50     q.clear();
51 }
52 inline bool check(const int &m) {
53     dijkstra(m);
54     return d[n]!=b+1;
55 }
56 int v[N];
57 int main() {
58     n=getint(),m=getint(),b=getint();
59     for(register int i=1;i<=n;i++) {
60         v[i]=f[i]=getint();
61     }
62     v[0]=inf;
63     std::sort(&v[0],&v[n+1]);
64     for(register int i=1;i<=m;i++) {
65         const int &u=getint(),&v=getint(),&w=getint();
66         add_edge(u,v,w);
67     }
68     int l=std::lower_bound(&v[0],&v[n+1],std::max(f[1],f[n]))-v,r=n;
69     while(l<r) {
70         const int mid=(l+r)>>1;
71         if(check(v[mid])) {
72             r=mid;
73         } else {
74             l=mid+1;
75         }
76     }
77     if(r!=n) {
78         printf("%d
",v[r]);
79     } else {
80         puts("AFK");
81     }
82     return 0;
83 }
原文地址:https://www.cnblogs.com/skylee03/p/7760482.html