ZOJ 3261 Connections in Galaxy War 【并查集 + 离线逆向处理】好题!!
2018-03-02 16:24
585 查看
传送门
// 题意: 给定一幅(n, m) 图, 每个点有点权, 然后有一些询问
destroy a b 表示摧毁a与b直接相连的边, 保证删除之前这两个点之间一定有边
query a 询问a可以到达的点中点权最大的且比a大, 如果有多种可能输出编号较小的. 没有输出-1.
思路:这道题的还是一个比较中规中矩的并查集, 一看到删边,我们想要想到逆向处理, 即倒着回到询问, 然后遇到删边的表示这两个点之间连边, 因为并查集只有将两个集合并起来的功能, 而无法处理集合的拆离, 所以我们倒着处理. 具体处理方法就是先把询问先存下来, 然后把要除去要删除的边之外的其他边连接上, 然后倒着一个一个回答, 遇到删除的就在连上这两个点即可!! 询问就查该点的父亲看点权是否大于本身即可, 还有一点就是因为武力值相同要编号小的是ans, 所以我们要在Union上做一些处理, 那就是那武力值小的往大的上面并, 武力值相同的就让编号大的往小的上面并即可.
这道题最重要的收获点就是即把集合的拆离可以转换成集合之间的合并!!!
AC Code
// 题意: 给定一幅(n, m) 图, 每个点有点权, 然后有一些询问
destroy a b 表示摧毁a与b直接相连的边, 保证删除之前这两个点之间一定有边
query a 询问a可以到达的点中点权最大的且比a大, 如果有多种可能输出编号较小的. 没有输出-1.
思路:这道题的还是一个比较中规中矩的并查集, 一看到删边,我们想要想到逆向处理, 即倒着回到询问, 然后遇到删边的表示这两个点之间连边, 因为并查集只有将两个集合并起来的功能, 而无法处理集合的拆离, 所以我们倒着处理. 具体处理方法就是先把询问先存下来, 然后把要除去要删除的边之外的其他边连接上, 然后倒着一个一个回答, 遇到删除的就在连上这两个点即可!! 询问就查该点的父亲看点权是否大于本身即可, 还有一点就是因为武力值相同要编号小的是ans, 所以我们要在Union上做一些处理, 那就是那武力值小的往大的上面并, 武力值相同的就让编号大的往小的上面并即可.
这道题最重要的收获点就是即把集合的拆离可以转换成集合之间的合并!!!
AC Code
const int maxn = 1e4+5; int n, m; int fa[maxn], _rank[maxn]; struct node{ int u, v; }e[maxn<<1]; void init() { for (int i = 0 ; i <= n ; i ++) { fa[i] = i; } } int Find(int x) { return fa[x] == x ? x : fa[x] = Find(fa[x]); } void Un(int x, int y) { int fx = Find(x); int fy = Find(y); if (fx != fy) { if (_rank[fx] < _rank[fy]) fa[fx] = fy; else if (_rank[fy] < _rank[fx]) fa[fy] = fx; else { if (fx < fy) swap(fx, fy); fa[fx] = fy; } } } struct query { string op; int a, b; }qq[maxn*5]; int ans[maxn*5]; void solve() { int cnt = 0; while(~scanf("%d", &n)) { if (cnt) printf("\n"); init(); map<pii, int>mp; for (int i = 0 ; i < n ; i ++) { scanf("%d", &_rank[i]); } scanf("%d", &m); for (int i = 1 ; i <= m ; i ++) { scanf("%d%d", &e[i].u, &e[i].v); } int q; scanf("%d", &q); for (int i = 1 ; i <= q ; i ++) { cin >> qq[i].op; if (qq[i].op == "query") scanf("%d", &qq[i].a); else { scanf("%d%d", &qq[i].a, &qq[i].b); mp[{qq[i].a, qq[i].b}] = mp[{qq[i].b, qq[i].a}] = 1; } } for (int i = 1 ; i <= m ; i ++) { int u = e[i].u, v = e[i].v; if (mp[{u, v}]) continue; Un(u, v); } int k = 0; for (int i = q ; i >= 1 ; i --) { if (qq[i].op == "query") { int fu = Find(qq[i].a); if (_rank[fu] <= _rank[qq[i].a]) ans[++k] = -1; else ans[++k] = fu; } else Un(qq[i].a, qq[i].b); } for (int i = k ; i >= 1 ; i --) { printf("%d\n", ans[i]); } cnt++; } }
相关文章推荐
- ZOJ 3261 Connections in Galaxy War (离线处理+逆向并查集)
- ZOJ 3261 Connections in GalaxyWar(并查集:离线处理)
- ZOJ 3261 Connections in Galaxy War(逆向处理)
- ZOJ 3261 Connections in Galaxy War(逆向并查集)
- Zoj 3261 Connections in Galaxy War (逆向并查集)
- ZOJ 3261 Connections in Galaxy War(逆向并查集)
- ZOJ-3261-Connections in Galaxy War [逆向并查集]
- ZOJ-3261 Connections in Galaxy War 并查集 离线操作
- ZOJ 3261 Connections in Galaxy War【并查集】
- [并查集+路径压缩]zoj 3261:Connections in Galaxy War
- ZOJ 3261 Connections in Galaxy War【并查集】
- ZOJ 3261 Connections in Galaxy War 并查集
- ZOJ 3261 Connections in Galaxy War 并查集
- ZOJ 3261 - Connections in Galaxy War ,并查集删边
- ZOJ 3261 Connections in Galaxy War 反向用并查集
- ZOJ-3261(Connections in Galaxy War)——并查集
- ZOJ Problem Set - 3261 Connections in Galaxy War(并查集)
- ZOJ 3261 Connections in Galaxy War(并查集)
- ZOJ 3261 Connections in Galaxy War (并查集)
- zoj 3261 Connections in Galaxy War 删边并查集模板