P3645 [APIO2015] 根号分治 + BFS

题意

传送门 P3645 [APIO2015]雅加达的摩天楼

题解

边权为 1 1 1 的图, B F S BFS BFS 即可。考虑 d o g e doge doge 的状态,为位置与跳跃能力的二元组,用 ( b , p ) (b,p) (b,p) 表示。若跳跃能力为 p p p,则其可达位置数为 N / p N/p N/p

考虑根号分治。若 p < N p<\sqrt N p<N ,状态数至多为 O ( N N ) O(N\sqrt N) O(NN );若 p ≥ N p\geq \sqrt N pN ,状态数至多为 O ( M N ) O(M\sqrt N) O(MN ) S T L   b i t s e t STL\ bitset STL bitset 记录状态, B F S BFS BFS 求解,总时间复杂度 O ( N N ) O(N\sqrt N) O(NN )

#include <bits/stdc++.h>
using namespace std;
const int maxn = 30005, maxs = 10000005;
struct node
{
    
    
    int b, p, d;
} Q[maxs];
int N, M, S, T, L, R;
bool vsb[maxn];
vector<int> pos[maxn];
bitset<maxn> vs[maxn];

inline void psh(int b, int p, int d)
{
    
    
    if (!vs[b][p])
        Q[++R] = node{
    
    b, p, d}, vs[b][p] = 1;
}

inline void upd(int b, int p, int d)
{
    
    
    psh(b, p, d);
    if (!vsb[b])
    {
    
    
        vsb[b] = 1;
        for (auto &q : pos[b])
            psh(b, q, d);
    }
}

int bfs()
{
    
    
    vsb[S] = 1;
    L = 1, R = 0;
    for (auto &p : pos[S])
        psh(S, p, 0);
    while (L <= R)
    {
    
    
        node &t = Q[L++];
        if (t.b == T)
            return t.d;
        if (t.b - t.p >= 0)
            upd(t.b - t.p, t.p, t.d + 1);
        if (t.b + t.p < N)
            upd(t.b + t.p, t.p, t.d + 1);
    }
    return -1;
}

int main()
{
    
    
    scanf("%d%d", &N, &M);
    for (int i = 0, b, p; i < M; ++i)
    {
    
    
        scanf("%d%d", &b, &p), pos[b].push_back(p);
        if (i == 0)
            S = b;
        if (i == 1)
            T = b;
    }
    printf("%d\n", bfs());
    return 0;
}

猜你喜欢

转载自blog.csdn.net/neweryyy/article/details/114852125