玲珑杯 Round 24 C 题 【思维好题!!! + bitset标记状态】

传送门
// 题意: 给你一个无向图,每次查询的时候给一堆二元组(xi,yi)
求图中有多少个点u与至少一个这次询问给出的二元组(xi,yi)满足dist(u,xi)<=yi,dist表示这两个点在图中的距离
如果不连通dist = inf

// 思路: 我们考虑用压位进行优化, f[i][j] 表示的是这幅图中到达i点的距离 <= j 的所有点构成的bitset集合, 然后查询的时候就是把一堆bitset or 起来就行啦. 所以我们先bfs每一个点预处理出f数组的值, 并做一个前缀就预处理完成了. 复杂度为O(nm + a*1000/32 + n*n*1000/32).

这道题很坑, 说几点. 一是要使用读入挂进行优化数据读入. 二是我们要去掉一些重边, 就用一个数组标记下就行啦. 知道这些注意点后就好敲了. (总之这道题非常的坑). 具体细节请看代码实现.

AC Code

const int maxn = 1e3+5;
int cas=1;
int Read() {
    int x = 0, f = 1;
    char ch;
    ch = getchar();
    while(ch<'0' || ch>'9') {
        if(ch=='-')  f = -1;
        ch = getchar();
    }
    while(ch>='0' && ch<='9')
        x = x*10+ch-'0', ch = getchar();
    return x*f;
}
struct node{
    int to, next, step;
};
bitset<1005>f[maxn][maxn];
int g[maxn][maxn];
vector<int>G[maxn];
int n, m;
bool vis[maxn];
void bfs(int st) {
    queueq; Fill(vis, false);
    q.push(node{st, 0, 0}); vis[st] = 1;
    while(!q.empty()) {
        node u = q.front();
        q.pop();
        f[st][u.step][u.to] = 1;

        for (auto i : G[u.to]) {
            if (vis[i]) continue;
            vis[i] = 1;
            q.push(node{i, 0, u.step+1});
        }
    }
}

void solve()
{
    int q;
    scanf("%d%d%d", &n, &m, &q);
    for(int i = 1 ; i <= m ; i ++) {
        int u, v;
        u = Read(); v = Read();
        if (g[u][v] || u == v) continue;
        g[u][v] = g[v][u] = 1;
        G[u].pb(v); G[v].pb(u);
    }
    for (int i = 1 ; i <= n ; i ++) {
        bfs(i);
        for (int j = 1 ; j <= n ; j ++) {
            f[i][j] |= f[i][j-1];
        }
    }
    while(q--) {
        bitset<1005>bit;
        int a = Read();
        for (int i = 1 ; i <= a ; i ++) {
            int x, y;
            x = Read(); y = Read();
            bit |= f[x][min(y, n)];
        }
        printf("%d\n", bit.count());
    }
}

你可能感兴趣的:(BFS/DFS搜索or暴力模拟,二进制思维/状压/bitset,想法思维题)