BZOJ 4668 冷战——并查集+LCA
基情链接♂BZOJ 1977 严格次小生成树——浅析最近公共祖先(LCA)
目录
一.题目:冷战
1.题目描述
2.输入
3.输出
4.样例输入
5.样例输出
二.题解
三.代码
谢谢!
一.题目:冷战
1.题目描述
1946 年 3 月 5 日,英国前首相温斯顿·丘吉尔在美国富尔顿发表“铁幕演说”,正式拉开了冷战序幕。美国和苏联同为世界上的“超级大国”,为了争夺世界霸权,两国及其盟国展开了数十年的斗争。在这段时期,虽然分歧和冲突严重,但双方都尽力避免世界范围的大规模战争(第三次世界大战)爆发,其对抗通常通过局部代理战争、科技和军备竞赛、太空竞争、外交竞争等“冷”方式进行,即“相互遏制,不动武力”,因此称之为“冷战”。Reddington 是美国的海军上将。由于战争局势十分紧张,因此他需要时刻关注着苏联的各个活动,避免使自己的国家陷入困境。苏联在全球拥有 N 个军工厂,但由于规划不当,一开始这些军工厂之间是不存在铁路的,为了使武器制造更快,苏联决定修建若干条道路使得某些军工厂联通。Reddington 得到了苏联的修建日程表,并且他需要时刻关注着某两个军工厂是否联通,以及最早在修建哪条道路时会联通。
具体而言,现在总共有M 个操作,操作分为两类:
• 0 u v,这次操作苏联会修建一条连接 u 号军工厂及 v 号军工厂的铁路,注意铁路都是双向的;
• 1 u v, Reddington 需要知道 u 号军工厂及 v 号军工厂最早在加入第几条条铁路后会联通,假如到这次操作都没有联通,则输出 0;
作为美国最强科学家, Reddington 需要你帮忙设计一个程序,能满足他的要求。
2.输入
第一行两个整数 N, M。
接下来 M 行,每行为 0 u v 或 1 u v 的形式。
数据是经过加密的,对于每次加边或询问,真正的 u, v 都等于读入的u, v 异或上上一次询问的答案。一开始这个值为 0。
1 ≤ N, M ≤ 500000,解密后的 u, v 满足1 ≤ u, v ≤ N, u不等于v
3.输出
对于每次 1 操作,输出 u, v 最早在加入哪条边后会联通,若到这个操作时还没联通,则输出 0。
4.样例输入
5 9
0 1 4
1 2 5
0 2 4
0 3 4
1 3 1
0 7 0
0 6 1
0 1 6
1 2 6
5.样例输出
0
3
5
二.题解
这道题第一眼看是并查集,对吧。但是不能直接用并查集做,因为要超时。我们可以将并查集和LCA联用起来。
首先因为我们只要两点相连通就行了。为避免成环,运用并查集判断连点是否连通。
又因为要找两个点最早多久连通,所以将i,即输入的序号当做权值,用一个数组val[i]存权值,表示点i到他父亲的权值,附权值就在启发式合并的时候进行就行了。注意:这里的并查集不能用路径压缩,因为我们后边要用fa[i]来爬山,所以要用启发式合并。
不用路径压缩找根结点:
int findSet (int x){while (x != fa[x])x = fa[x];return x;
}
启发式合并+附边权:
void unionSet (int x, int y, int w){int u = findSet (x), v = findSet (y);if (u == v)return ;if (Rank[u] >= Rank[v]){fa[v] = u;val[v] = w;if (Rank[u] == Rank[v])Rank[u] ++;}else{fa[u] = v;val[u] = w;}
}
然后在遇到要输出的时候,先用并查集判断两点是否在同一颗树上,如果在,就进入LCA函数;否则,输出0。首先将每个点的深度预处理一下,然后可以直接用暴力爬山法,先将两点爬到同一深度,再爬到LCA。爬的路程中爬一步比较一下最大权值,最后输出最大权值就行了。
深度预处理:
void prepare (int x){//dep[i]指深度if (x == fa[x])return ;prepare (fa[x]);dep[x] = dep[fa[x]] + 1;
}
是不是很简单?注意要异或!
三.代码
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
#define M 500005
int fa[M], n, m, Xor, dep[M], Rank[M], val[M], num;
void makeSet (int x){for (int i = 0; i <= x; i ++)fa[i] = i;
}
int findSet (int x){while (x != fa[x])x = fa[x];return x;
}
void prepare (int x){if (x == fa[x])return ;prepare (fa[x]);dep[x] = dep[fa[x]] + 1;
}
void unionSet (int x, int y, int w){int u = findSet (x), v = findSet (y);if (u == v)return ;if (Rank[u] >= Rank[v]){fa[v] = u;val[v] = w;if (Rank[u] == Rank[v])Rank[u] ++;}else{fa[u] = v;val[u] = w;}
}
int answer_question (int x, int y){int Max = 0;prepare (x);prepare (y);if (dep[x] < dep[y])swap (x, y);while (dep[x] > dep[y]){Max = max (val[x], Max);x = fa[x];}while (x != y){Max = max (val[x], Max), Max = max (val[y], Max);x = fa[x], y = fa[y];}return Max;
}
int main (){scanf ("%d %d", &n, &m);makeSet (n);int u, v, flag;for (int i = 1; i <= m; i ++){scanf ("%d %d %d", &flag, &u, &v);u = u ^ Xor;v = v ^ Xor;if (! flag){num ++;unionSet (u, v, num);}else{int x = findSet (u), y = findSet (v);if (x != y)Xor = 0;elseXor = answer_question (u, v);printf ("%d\n", Xor);}}return 0;
}
谢谢!
BZOJ 4668 冷战——并查集+LCA相关推荐
- BZOJ 4668: 冷战 并查集暴力LCA(雾)
利用并查集按秩合并,保存每个点合并的时间: 求时间时,就一直跳u=fa[u],并记录路径上时间的最大值,代表最后一次合并的时间 #include<cstdio> #include<i ...
- BZOJ 4668: 冷战 并查集
Time Limit: 10 Sec Memory Limit: 256 MB Submit: 440 Solved: 215 Description 1946 年 3 月 5 日,英国前首相温斯顿· ...
- BZOJ 4668 冷战(按秩合并并查集+LCA)
4668: 冷战 Time Limit: 10 Sec Memory Limit: 256 MB Submit: 627 Solved: 303 [Submit][Status][Discuss] ...
- BZOJ4668: 冷战 [并查集 按秩合并]
BZOJ4668: 冷战 题意: 给定 n 个点的图.动态的往图中加边,并且询问某两个点最早什 么时候联通,强制在线. 还可以这样乱搞 并查集按秩合并的好处: 深度不会超过\(O(\log n)\) ...
- [BZOJ]4668: 冷战
题解:我们考虑按秩合并 保证每个点往上跳logn层 然后并查集维护就行 #include <algorithm> #include <iostream> #include ...
- HDU - 2874 Connections between cities(并查集+LCA)
题目链接:点击查看 题目大意:给出n个点代表城市,再给出m条边将其连接,每条边都有边权,题目保证给出的图无环,现在给出两个点,首先询问两个点是否互相连通,若可以连通,询问两点之间的距离 题目分析:判断 ...
- jzoj5097-[GDOI2017day1]取石子游戏【并查集,LCA】
正题 题目链接:https://gmoj.net/senior/#main/show/5097 题目大意 nnn个点的一棵树,每个节点有权值.对于每个点求树上所有权值去除掉他的子树的权值后的mexme ...
- [ BZOJ 4668 ] 冷战
\(\\\) \(Description\) 有\(N\)个点,开始没有边相连,进行按顺序给出的\(M\)个操作: \(0\ u\ v\) 将\(u,v\)两点连一条边 \(1\ u\ v\) 查询\ ...
- 【BZOJ4668】冷战 并查集
[BZOJ4668]冷战 Description 1946 年 3 月 5 日,英国前首相温斯顿·丘吉尔在美国富尔顿发表"铁幕演说",正式拉开了冷战序幕. 美国和苏联同为世界上的& ...
最新文章
- 监控Linux服务器网站状态的SHELL脚本
- Android可输入的下拉框,android 可编辑的下拉框 Demo
- 碎碎念 | 投资理财那些事
- perl学习笔记(9)
- css3 transform matrix 深入理解
- switch语句使用注意事项
- 56PY宿迁味道这么可口
- 信息学奥赛一本通 1200:分解因数 | OpenJudge 2.2 1751:分解因数
- twitter java_Twitter算法面试题详解(Java实现)
- vue+element Form键盘回车事件页面刷新解决
- URLClassLoader使用方法及事例程序
- 专访腾讯云谢岳峰:只做连接器,五大措施支持渠道伙伴成长
- 戴尔笔记本插入耳机没有反应
- 百度地图开发者使用教程
- 解决nrm ls命令没有*(星号)的问题
- java丐帮_JAVA集合 list set map
- 基于OHCI的USB主机 —— UFI数据结构3
- 2015 macbook air换第三方SSD(西数SN750)
- 查询mysql的引擎
- Android KeyLogger Demo