Loading... ## 题目链接 [链接](https://pintia.cn/problem-sets/1446838676759703552/exam/problems/1446838732288094211) ## 题目大意 n个点,m条路径,d次询问,每次锁定一个点c,给出q条边,问,q条边在锁定c点后多少条边无法连通 ## 题解 并查集支持加一些点进去来判断是不是在一个集合,但是如果删去一个点就不知道多少个点会受影响,所以,这道题的精华就是倒过来,先将那些从来没有锁定的点构建并查集,然后倒过来处理,每次释放一个点,并查集维护没有锁定点的集合。 ## 代码 ```cpp #include <algorithm> #include <bitset> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <fstream> #include <iostream> #include <map> #include <queue> #include <set> #include <stack> #include <unordered_map> #include <unordered_set> #include <vector> #define x first #define y second #define endl '\n' #define IOS \ ios_base::sync_with_stdio(0); \ cin.tie(0); \ cout.tie(0); using namespace std; typedef long long ll; typedef pair<ll, ll> pll; typedef pair<int, int> pii; typedef unsigned long long ull; const int INF = 0x3f3f3f3f, mod = 1000000007; const int N = 2e5 + 10; int n, m, d; int day[N], p[N]; vector<int> a[N]; vector<pii> v[N]; map<int, int> vis; int find(int x) { if (x != p[x]) p[x] = find(p[x]); return p[x]; } void solve() { cin >> n >> m >> d; for (int i = 1; i <= n; i++) { p[i] = i; } for (int i = 1; i <= m; i++) { int x, y; cin >> x >> y; a[x].push_back(y); a[y].push_back(x); } for (int i = 1; i <= d; i++) { int c, q; cin >> c >> q; day[i] = c; vis[c] = 1; while (q--) { int x, y; cin >> x >> y; v[i].push_back({x, y}); } } for(int i = 1; i <= n; i++){ if(vis[i]) continue; for(auto x : a[i]){ if(vis[x]) continue; int fx = find(x), fy = find(i); if(fx != fy) p[fx] = fy; } } stack<int> q; for (int i = d; i; i--) { int cnt = 0, c = day[i]; for(auto x : v[i]){ int fx = find(x.x), fy = find(x.y); if(fx != fy) cnt++; } q.push(cnt); for(auto x : a[c]){ if(vis[x]) continue; int fx = find(x), fy = find(c); if(fx != fy) p[fx] = fy; } vis[c] = 0; } while (q.size()) { cout << q.top() << endl; q.pop(); } } int main() { // IOS; int _ = 1; // cin >> _; while (_--) { solve(); } return 0; } ``` 最后修改:2023 年 07 月 12 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏