luoguP5068 [Ynoi2015]我回来了

https://www.luogu.org/problemnew/show/P5068

ynoi 中的良心题啊

考虑用 bitset 来维护里一个点距离小于 $ y_i $ 的点,那么答案就是一堆 bitset 或起来后二进制位中 $ 1 $ 的个数

这样我们只要令 $ f[i][j] $ 表示距离 $ i $ 点距离小于 $ j $ 的点,便可以高效求出答案

考虑怎么求出所有的 $ f[i][j] $

先枚举起点 $ u $,因为边权为 $ 1 $,所以只需要做一次 bfs

对于 $ i $ 这个点,假设它到 $ u $ 的距离为 $ dis_i $,那么我们就将 $ f[u][dis_i] $ 的第 $ i $ 位设为 $ 1 $,最后从小到大把 $ f[u][j] $ 或上 $ f[u][j - 1] $ 即可

复杂度是 $ \frac{n^3}{64} + (\sum\limits_{i=1}^{q}a_i)*\frac{n}{64} $,可以通过此题

最后 % 一发 lxl

#include <bits/stdc++.h>
#define CIOS ios::sync_with_stdio(false);
#define rep(i, a, b) for(register int i = a; i <= b; i++)
#define per(i, a, b) for(register int i = a; i >= b; i--)
#define DEBUG(x) cerr << "DEBUG" << x << " >>> ";
using namespace std;

typedef unsigned long long ull;
typedef long long ll;

template <typename T>
inline void read(T &f) {
    f = 0; T fu = 1; char c = getchar();
    while (c < '0' || c > '9') { if (c == '-') fu = -1; c = getchar(); }
    while (c >= '0' && c <= '9') { f = (f << 3) + (f << 1) + (c & 15); c = getchar(); }
    f *= fu;
}

template <typename T>
void print(T x) {
    if (x < 0) putchar('-'), x = -x;
    if (x < 10) putchar(x + 48);
    else print(x / 10), putchar(x % 10 + 48);
}

template <typename T>
void print(T x, char t) {
    print(x); putchar(t);
}

const int N = 1005, INF = 0x7f7f7f7f;

queue <int> q;
bitset <N> f[N][N], Ans;
vector <int> adj[N];
int dis[N][N], n, m, Q, now;

int main() {
    memset(dis, 0x7f, sizeof(dis));
    read(n); read(m); read(Q);
    for(register int i = 1; i <= m; i++) {
        int a, b; read(a); read(b);
        adj[a].push_back(b);
        adj[b].push_back(a);
    }
    for(register int i = 1; i <= n; i++) {
        q.push(i); dis[i][i] = 0; now = i; f[i][0].set(i);
        while(!q.empty()) {
            int u = q.front(); q.pop();
            for(register int j = 0; j < adj[u].size(); j++) {
                int v = adj[u][j];
                if(dis[i][v] == INF) {
                    dis[i][v] = dis[i][u] + 1;
                    q.push(v); f[i][dis[i][v]].set(v);
                }
            }
        }
        for(register int j = 1; j <= n; j++) f[i][j] |= f[i][j - 1];
    }
    while(Q--) {
        int t; read(t); Ans.reset();
        while(t--) {
            int a, b; read(a); read(b);
            if(b > n) b = n;
            Ans |= f[a][b];
        }
        print(Ans.count(), '\n');
    }
    return 0;
}
posted @ 2018-12-10 20:44  LJC00118  阅读(397)  评论(0编辑  收藏  举报
/*
*/