基情链接♂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相关推荐

  1. BZOJ 4668: 冷战 并查集暴力LCA(雾)

    利用并查集按秩合并,保存每个点合并的时间: 求时间时,就一直跳u=fa[u],并记录路径上时间的最大值,代表最后一次合并的时间 #include<cstdio> #include<i ...

  2. BZOJ 4668: 冷战 并查集

    Time Limit: 10 Sec Memory Limit: 256 MB Submit: 440 Solved: 215 Description 1946 年 3 月 5 日,英国前首相温斯顿· ...

  3. BZOJ 4668 冷战(按秩合并并查集+LCA)

    4668: 冷战 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 627  Solved: 303 [Submit][Status][Discuss] ...

  4. BZOJ4668: 冷战 [并查集 按秩合并]

    BZOJ4668: 冷战 题意: 给定 n 个点的图.动态的往图中加边,并且询问某两个点最早什 么时候联通,强制在线. 还可以这样乱搞 并查集按秩合并的好处: 深度不会超过\(O(\log n)\) ...

  5. [BZOJ]4668: 冷战

    题解:我们考虑按秩合并  保证每个点往上跳logn层   然后并查集维护就行 #include <algorithm> #include <iostream> #include ...

  6. HDU - 2874 Connections between cities(并查集+LCA)

    题目链接:点击查看 题目大意:给出n个点代表城市,再给出m条边将其连接,每条边都有边权,题目保证给出的图无环,现在给出两个点,首先询问两个点是否互相连通,若可以连通,询问两点之间的距离 题目分析:判断 ...

  7. jzoj5097-[GDOI2017day1]取石子游戏【并查集,LCA】

    正题 题目链接:https://gmoj.net/senior/#main/show/5097 题目大意 nnn个点的一棵树,每个节点有权值.对于每个点求树上所有权值去除掉他的子树的权值后的mexme ...

  8. [ BZOJ 4668 ] 冷战

    \(\\\) \(Description\) 有\(N\)个点,开始没有边相连,进行按顺序给出的\(M\)个操作: \(0\ u\ v\) 将\(u,v\)两点连一条边 \(1\ u\ v\) 查询\ ...

  9. 【BZOJ4668】冷战 并查集

    [BZOJ4668]冷战 Description 1946 年 3 月 5 日,英国前首相温斯顿·丘吉尔在美国富尔顿发表"铁幕演说",正式拉开了冷战序幕. 美国和苏联同为世界上的& ...

最新文章

  1. 监控Linux服务器网站状态的SHELL脚本
  2. Android可输入的下拉框,android 可编辑的下拉框 Demo
  3. 碎碎念 | 投资理财那些事
  4. perl学习笔记(9)
  5. css3 transform matrix 深入理解
  6. switch语句使用注意事项
  7. 56PY宿迁味道这么可口
  8. 信息学奥赛一本通 1200:分解因数 | OpenJudge 2.2 1751:分解因数
  9. twitter java_Twitter算法面试题详解(Java实现)
  10. vue+element Form键盘回车事件页面刷新解决
  11. URLClassLoader使用方法及事例程序
  12. 专访腾讯云谢岳峰:只做连接器,五大措施支持渠道伙伴成长
  13. 戴尔笔记本插入耳机没有反应
  14. 百度地图开发者使用教程
  15. 解决nrm ls命令没有*(星号)的问题
  16. java丐帮_JAVA集合 list set map
  17. 基于OHCI的USB主机 —— UFI数据结构3
  18. 2015 macbook air换第三方SSD(西数SN750)
  19. 查询mysql的引擎
  20. Android KeyLogger Demo

热门文章

  1. HSV色彩空间表和cv2.inRange()的用法
  2. 一致性Hash算法与虚拟节点
  3. java 分批读取文件_Java分批读取文件
  4. 【引语练习题】直接引语为疑问句转为间接引语时注意
  5. 【数学问题】最大质因数
  6. Oracle数据库数据同步方案,ORACLE数据库热备方案
  7. strftime()函数的使用方法
  8. CPLEX-分支定界算法调用cplex求解VRPTW
  9. 短视频,是信息的终极形态:如何抓住比特红短视频这个红利?
  10. 我心中未来的计算机作文200,未来的机器人作文200字