2021 RoboCom 世界机器人开发者大赛-本科组(初赛)7-4 疫情防控 (30 分)

题目大意:

给定一个 \(n\) 个顶点, \(m\) 条边的图,现在对图进行 \(d\) 次操作, 每次操作为标记编号为 \(c\) 的顶点不能走(即删除与 \(c\) 相连的边),每次操作中又有 \(q\) 次询问:编号 \(x\) 和 编号 \(y\) 之间是否有通路。

思路:

这个题目如果采用每次询问一次就遍历图,那么复杂度显然是 \(5 * 10000 * 1000 * 1000\), 显然会超时。因此,这种暴力 \(dfs\) 模拟算法不可行。

仔细一想,这个题目每次询问可以采取离线处理方式,然后利用并查集考虑两点是否有通路,即两个点在同一个集合就是形成了通路。采用逆向处理,先删除所有标记的 \(c\) 点,然后从后往前加点,不断更新并查集。

代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 50010, M = 400010;

int n, m, d;
int h[N], e[M], ne[M], idx;
vector<int> s;
vector<pair<int, int> > query[1010];
int p[N], ans[1010];
bool st[N];

void add(int a, int b){
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

int find(int x){
    if(x != p[x]) p[x] = find(p[x]);
    return p[x];
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    memset(h, -1, sizeof h);
    cin >> n >> m >> d;
    for(int i = 0; i < m; i++){
        int a, b;
        cin >> a >> b;
        add(a, b), add(b, a);
    }

    for(int i = 1; i <= n; i++) p[i] = i;

    for(int i = 0; i < d; i++) {
        int c, q;
        cin >> c >> q;
        st[c] = true;
        s.push_back(c);
        while(q --){
            int x, y;
            cin >> x >> y;
            query[i].push_back({x, y});
        }
    }

    for(int i = 1; i <= n; i++){
        if(st[i] == false){
            for(int j = h[i]; ~j; j = ne[j]){
                int t = e[j];
                if(st[t] == true) continue;
                int fa = find(i), fb = find(t);
                if(fa != fb) p[fa] = fb;
            }
        }
    }

    for(int i = d - 1; i >= 0; i--){
        for(int j = 0; j < query[i].size(); j++){
            int fx = find(query[i][j].first), fy = find(query[i][j].second);
            if(fx != fy) ans[i]++;
        }
        st[s[i]] = false;
        for(int k = h[s[i]]; ~k; k = ne[k]){
            int t = e[k];
            if(st[t] == false) p[find(t)] = find(s[i]);
        }

    }

    for(int i = 0; i < d; i++){
        cout << ans[i] << endl;
    }

    return 0;
}


上一篇:java递归 对应LeetCode39 40题目


下一篇:Qt ListView控件使用心得