NC235745 拆路
题目
题目描述
有 个城镇,城镇之间有 条道路相连,道路可以看成无向边。每一个城镇都有自己的一个繁荣度 ,一个城镇 受到的影响 是与 直接或者间接相连的所有城镇中,繁荣度的最大值。一个城镇 与城镇 是被视为直接或者间接相连的,当且仅当 或者从 出发,可以沿着某些道路到达 。为了减少维护成本,现准备拆除其中的某一些路。具体来说,你需要维护以下两种操作:
- 'Q' ,询问 城镇受到的影响 ;
- 'D' ,删除 之间的道路。
输入描述
第一行输入两个整数 ,分别表示城镇的数量和道路的数量。第二行输入 个整数 ,分别表示每一个城镇的繁荣度。接下来 行,每行两个整数 ,表示城镇 之间有一条道路连接。保证不含有重边、自环。
接下来一行,输入一个整数 ,表示操作的个数。
接下来 行,每行描述一个操作,以'Q' 或者'D' 的形式给出。对于删除操作,保证被删除的道路是存在的。
输出描述
对于每一个操作1,你都需要输出一个整数 ,表示城镇 受到的影响。
示例1
输入
4 3 1 2 3 4 1 2 2 3 3 4 4 Q 1 D 2 3 Q 1 Q 3
输出
4 2 4
题解
知识点:并查集,离线。
普通并查集不支持撤销操作,这使得这道题难以解答,但转换一下思路,撤销的逆过程是新增,是并查集适用的操作,于是可以保存所有访问数据,离线逆向处理,再将答案保存最后输出即可。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> using namespace std; int w[100007]; int u[100007], v[100007]; int du[100007], dv[100007]; set<pair<int, int>> s; int fa[100007]; int ans[100007]; int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); } void merge(int x, int y) { int rx = find(x); int ry = find(y); if (w[rx] < w[ry]) fa[rx] = ry; else fa[ry] = rx; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int n, m; cin >> n >> m; for (int i = 1;i <= n;i++) fa[i] = i; for (int i = 1;i <= n;i++) cin >> w[i]; for (int i = 1;i <= m;i++) cin >> u[i] >> v[i]; int q; cin >> q; for (int i = 1;i <= q;i++) { char op; cin >> op; if (op == 'Q') cin >> du[i]; else if (op == 'D') { cin >> du[i] >> dv[i]; s.insert({ du[i],dv[i] }); s.insert({ dv[i],du[i] }); } } for (int i = 1;i <= m;i++) if (s.find({ u[i],v[i] }) == s.end()) merge(u[i], v[i]); for (int i = q;i >= 1;i--) { if (dv[i]) merge(du[i], dv[i]); else ans[i] = w[find(du[i])]; } for (int i = 1;i <= q;i++) { if (ans[i]) cout << ans[i] << '\n'; } return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16464224.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧