APIO2015 雅加达的摩天楼

首先可以看出这是一道求最短路的题目,但暴力建图最多n2 条边,所以考虑建图优化

对于p>sqrt(n) 的青蛙可以直接暴力建,最多n*sqrt(n) 条边

对于p<sqrt(n) 的青蛙添加辅助点,枚举这sqrt(n)个长度,每个长度建立n个辅助点前后对应连边,同时向它们可以到达的点以及可以到达它们的点连边

 1 #define MAXN 4000010UL
 2 #include <cstdio>
 3 #include <queue>
 4 #include <cmath>
 5 #include <cstring>
 6 
 7 using namespace std;
 8 
 9 int n, m, t, inf, S, T, d[MAXN], dis[MAXN], mp[30010][175];
10 bool ins[MAXN];
11 
12 struct Edge {
13     int hou, nt, zhi;
14 }sg[MAXN<<2];
15 
16 void Add(int x, int y, int z) {
17     sg[t] = (Edge){y, d[x], z}, d[x] = t ++;
18     return;
19 }
20 
21 void Spfa(int x) {
22     memset(dis, 0x3f, sizeof(dis));
23     inf = dis[0];
24     dis[x] = 0;
25     queue <int> q; q.push(x);
26     while(!q.empty()) {
27         int op = q.front(); q.pop();
28         ins[op] = false;
29         for(int i = d[op] ; i != -1 ; i = sg[i].nt) if(dis[sg[i].hou]>dis[op]+sg[i].zhi) {
30             dis[sg[i].hou] = dis[op]+sg[i].zhi;
31             if(!ins[sg[i].hou]) {
32                 ins[sg[i].hou] = true;
33                 q.push(sg[i].hou);
34             }
35         }
36     }
37     return;
38 }
39 
40 int main() {
41     memset(d, -1, sizeof(d));
42     scanf("%d%d", &n, &m);
43     int blo = (int)sqrt(n), tot = n-1;
44     for(int i = 0 ; i < n ; ++ i) {
45         for(int j = 1 ; j <= blo ; ++ j) mp[i][j] = ++ tot, Add(tot, i, 0);
46     }
47     
48     for(int i = 0 ; i < n ; ++ i) {
49         for(int j = 1 ; j <= blo ; ++ j) {
50             if(i+j<n) Add(mp[i][j], mp[i+j][j], 1);
51             if(i-j>=0) Add(mp[i][j], mp[i-j][j], 1);
52         }
53     }
54     for(int i = 0, b, p ; i < m ; ++ i) {
55         scanf("%d%d", &b, &p);
56         if(i==0) S = b;
57         if(i==1) T = b;
58         if(p<=blo) Add(b, mp[b][p], 0);
59         else {
60             for(int j = 1 ; b+j*p < n ; ++ j) Add(b, b+j*p, j);
61             for(int j = 1 ; b-j*p >= 0 ; ++ j) Add(b, b-j*p, j);
62         }
63     }
64     Spfa(S);
65     if(dis[T]==inf) printf("-1");
66     else printf("%d", dis[T]);
67     return 0;
68 }
View Code
原文地址:https://www.cnblogs.com/assassain/p/5439841.html