【洛谷习题】通往奥格瑞玛的道路

题目的描述就很有意思,可以顺便去了解一下魔兽的背景故事。学习使我们快乐!

题目链接:https://www.luogu.org/problemnew/show/P1462


大清早上起来A掉一道题,好兴奋。看到题目要求收费最多的一次的最小值,想到用二分答案,二分这个最小值,然后去跑最短路,看是否可以,再不断更新区间,使这个值尽量小。几乎没有什么难点,但需要注意的细节有几个。估计答案的最大值应为收费最多的城市所收的费用;检验时,我是采用若发现某个结点的收费比当前所验证的答案大,则不再扩展,最后通过检查是否存在最短路,最短路是否可以回到奥格瑞玛,但问题是,如果终点不符合要求,同样会存在最短路,最短路可能也可以回到奥格瑞玛,所以还需要额外检查终点是否不超过检验的答案。

还有,无向图用邻接表存储时,每条边会存两次!!!

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 
 5 using namespace std;
 6 
 7 inline int get_num() {
 8     int num = 0;
 9     char c = getchar();
10     while (c < '0' || c > '9') c = getchar();
11     while (c >= '0' && c <= '9')
12         num = num * 10 + c - '0', c = getchar();
13     return num;
14 }
15 
16 const int maxn = 1e4 + 5, maxm = 5e4 + 5, inf = 0x3f3f3f3f;
17 
18 int head[maxn], eid;
19 
20 struct Edge {
21     int v, w, next;
22 } edge[2 * maxm];
23 
24 inline void insert(int u, int v, int w) {
25     edge[++eid].v = v;
26     edge[eid].w = w;
27     edge[eid].next = head[u];
28     head[u] = eid;
29 }
30 
31 struct node {
32     int id, dist;
33     node(int i, int d) : id(i), dist(d) {}
34     bool operator < (const node& rhs) const {
35         return dist > rhs.dist;
36     }
37 };
38 
39 int n, m, b, f[maxn], dist[maxn], vis[maxn];
40 
41 priority_queue<node> q;
42 
43 inline int check(int x) {
44     memset(vis, 0, sizeof(vis));
45     memset(dist, inf, sizeof(dist));
46     dist[1] = 0;
47     q.push(node(1, 0));
48     while (!q.empty()) {
49         int u = q.top().id;
50         q.pop();
51         if (vis[u]) continue;
52         vis[u] = 1;
53         for (int p = head[u]; p; p = edge[p].next) {
54             int v = edge[p].v, w = edge[p].w;
55             if (f[v] > x) continue;
56             if (dist[v] > dist[u] + w) {
57                 dist[v] = dist[u] + w;
58                 q.push(node(v, dist[v]));
59             }
60         }
61     }
62     if (dist[n] > b) return 0;
63     else return 1;
64 }
65 
66 int main() {
67     n = get_num(), m = get_num(), b = get_num();
68     int mf = 0;
69     for (int i = 1; i <= n; ++i) {
70         f[i] = get_num();
71         if (f[i] > mf) mf = f[i];
72     }
73     for (int i = 1; i <= m; ++i) {
74         int u = get_num(), v = get_num(), w = get_num();
75         insert(u, v, w);
76         insert(v, u, w);
77     }
78     if (!check(mf)) {printf("AFK"); return 0;}
79     int l = 1, r = mf;
80     while (l < r) {
81         int mid = l + (r - l) / 2;
82         if (check(mid)) r = mid;
83         else l = mid + 1;
84     }
85     printf("%d", l);
86     return 0;
87 }
AC代码
原文地址:https://www.cnblogs.com/Mr94Kevin/p/9539894.html