题意:给你一张无向图,无向图中每条边有颜色。有两种操作,一种是询问从x到y是否有双彩虹路,一种是在x到y之间添加一条颜色为z的边。双彩虹路是指:如果给这条路径的点编号,那么第i个点和第i - 1个点相连的边与第i个点和第i + 1个点相连的边颜色一样,其中i是偶数。

思路:这个问题相当于初了最后一步没有限制以外(最后一步只走一条边),每一步都要走颜色相同的两条边。我们先不考虑最后一步的问题,只考虑每一步都要走颜色相同的两条边,那么我们只需要扫描每一个点的出边,如果有两条边颜色相同,就在一张新图上把这两条边除这个点以外的端点相连,这样询问就变成了判断两个点是否在一个连通块中。因为只是判断是否在同一连通块中,我们不需要建图,用并查集就可以了。现在需要考虑最后一步的问题,我们可以用一个set维护与这个节点直接相邻的点,这样对于询问x, y,如果y在连通块x的相邻节点中,也可以。对于加边的操作,相当于并查集的合并,但是同时需要合并的还有set, 我们合并的时候需要判断一下两个集合的大小,把小的插入大的里面,这样可以保证每次集合合并复杂度是O(logn * logn)的。

代码:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int maxn = 100010;
  4. set<int> s[maxn];
  5. set<int>::iterator it1;
  6. set<pair<int, int> > edge[maxn];
  7. set<pair<int, int> >::iterator it;
  8. int f[maxn];
  9. int get(int x) {
  10. if(x == f[x]) return x;
  11. return f[x] = get(f[x]);
  12. }
  13. void merge(int x, int y) {
  14. int x1 = get(x), y1 = get(y);
  15. if(x1 == y1) return;
  16. if(s[x1].size() < s[y1].size()) swap(x1, y1);
  17. for (it1 = s[y1].begin(); it1 != s[y1].end(); it1++) {
  18. s[x1].insert(*it1);
  19. }
  20. s[y1].clear();
  21. f[y1] = x1;
  22. }
  23. void add(int x, int y, int z) {
  24. s[get(x)].insert(y);
  25. it = edge[x].lower_bound(make_pair(z, -1));
  26. if(it == edge[x].end() || it -> first != z) {
  27. edge[x].insert(make_pair(z, y));
  28. } else {
  29. merge(it -> second, y);
  30. }
  31. }
  32. int main() {
  33. int x, y, z, n, m, c, T;
  34. char op[5];
  35. scanf("%d%d%d%d", &n, &m, &c, &T);
  36. for (int i = 1; i <= n; i++) f[i] = i;
  37. for (int i = 1; i <= m; i++) {
  38. scanf("%d%d%d", &x, &y, &z);
  39. add(x, y, z);
  40. add(y, x, z);
  41. }
  42. while(T--) {
  43. scanf("%s", op + 1);
  44. if(op[1] == '+') {
  45. scanf("%d%d%d", &x, &y, &z);
  46. add(x, y, z);
  47. add(y, x, z);
  48. } else {
  49. scanf("%d%d", &x, &y);
  50. if(get(x) == get(y)) {
  51. printf("Yes\n");
  52. } else if(s[get(x)].find(y) != s[get(x)].end()) {
  53. printf("Yes\n");
  54. } else {
  55. printf("No\n");
  56. }
  57. }
  58. }
  59. }

  

Codeforces 1166F 并查集 启发式合并的更多相关文章

  1. BZOJ2733[HNOI2012]永无乡——线段树合并+并查集+启发式合并

    题目描述 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达 ...

  2. BZOJ 4668: 冷战 并查集启发式合并/LCT

    挺好想的,最简单的方法是并查集启发式合并,加暴力跳父亲. 然而,这个代码量比较小,比较好写,所以我写了 LCT,更具挑战性. #include <cstdio> #include < ...

  3. [HDU 3712] Fiolki (带边权并查集+启发式合并)

    [HDU 3712] Fiolki (带边权并查集+启发式合并) 题面 化学家吉丽想要配置一种神奇的药水来拯救世界. 吉丽有n种不同的液体物质,和n个药瓶(均从1到n编号).初始时,第i个瓶内装着g[ ...

  4. [BZOJ 4668]冷战(带边权并查集+启发式合并)

    [BZOJ 4668]冷战(并查集+启发式合并) 题面 一开始有n个点,动态加边,同时查询u,v最早什么时候联通.强制在线 分析 用并查集维护连通性,每个点x还要另外记录tim[x],表示x什么时间与 ...

  5. BZOJ 3673: 可持久化并查集(可持久化并查集+启发式合并)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3673 题意: 思路: 可持久化数组可以用可持久化线段树来实现,并查集的查询操作和原来的一般并查集操作 ...

  6. codeforces#1166F. Vicky's Delivery (Service并查集+启发式合并)

    题目链接: https://codeforces.com/contest/1166/problem/F 题意: 给出节点数为$n$,边数为$m$的图,保证每个点对都是互连的 定义彩虹路:这条路经过$k ...

  7. [bzoj3123][sdoi2013森林] (树上主席树+lca+并查集启发式合并+暴力重构森林)

    Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...

  8. 2018.08.21 bzoj4668: 冷战(并查集+启发式合并)

    传送门 可以发现需要维护连通性和两点连通时间. 前者显然是并查集的常规操作,关键就在于如何维护两点的连通时间. 然后会想到这个时候不能用路径压缩了,因为它会破坏原本树形集合的结构,因此可以启发式按si ...

  9. BZOJ4602: [Sdoi2016]齿轮(并查集 启发式合并)

    题意 题目链接 Sol 和cc的一道题很像啊 对于初始的\(N\)个点,每加一条限制实际上就是合并了两个联通块. 那么我们预处理出\(val[i]\)表示的是\(i\)节点所在的联通块根节点转了\(1 ...

随机推荐

  1. ubuntu 安装 docker

    安装命令 sudo apt-get update sudo apt-get install docker.io 启动docker后台服务 sudo service docker start 1.删除镜 ...

  2. 【虚拟机】:"该虚拟机似乎正在使用中。 如果该虚拟机未在使用,请按“获取所有权(T)”按钮获取它的所有权。否则,请按“取消(C)”按钮以防损坏。"

    1.可能是由于上次使用虚拟机,没有正常关闭出现了这种情况,于是把问题复制粘贴搜了一下. 2.出现了如下可行的解决方法:把后缀名为.vmdk.lck的都删除掉. 3.然后再打开虚拟机就可以了.

  3. Bootstrap 网页实例

    代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <met ...

  4. 【Flutter学习】之DateTime日期转换

    概述: 表示一个时间点 通过构造函数或解析格式化的字符串创建DateTime对象,并且符合ISO 8601标准的子集,小时是24小时制,范围在0-23之间 DateTime对象创建之后,将是固定不变的 ...

  5. zoj 2112 单点修改的主席树(树状数组套主席树)

    题目大意: 区间第k大问题+单点修改 基本思路: 这个题有用整体二分,cdq分治,还有主席树+平衡树的,还有就是主席树+树状数组. 我采用的是b站电子科大大佬的主席树写法,尤其喜欢他的离散化方法,所以 ...

  6. Win7 VS2012智能提示显示英文的处理办法

    其原因为.net的语言包没安装成功, 解决方法为 替换自己英文显示的,把C:\Windows\Microsoft.NET\Framework\v2.0.50727\zh-CN 目录的文件,替换到相应的 ...

  7. boost库:多线程

    1.线程管理 最重要的一个类是boost::thread,是在boost/thread.hpp里定义的,用来创建一个新线程. #include <boost/thread.hpp> #in ...

  8. 【InnoDB】插入缓存,两次写,自适应hash索引

    InnoDB存储引擎的关键特性包括插入缓冲.两次写(double write).自适应哈希索引(adaptive hash index).这些特性为InnoDB存储引擎带来了更好的性能和更高的可靠性. ...

  9. MaxCompute问答整理之10月

    本文是基于本人对MaxCompute产品的学习进度,再结合开发者社区里面的一些问题,进而整理成文.希望对大家有所帮助. 问题一.DataStudio中是否可以通过shell节点调取MaxCompute ...

  10. 【C#、阿里云、Tomcat、XP系统】c#下使用.NET4.0中HttpWebRequest访问Tomcat中HTTPS项目时,在XP系统中超时

    情景: 1.使用Java开发的Web项目,部署在服务器Tomcat中 2.项目使用HTTPS,使用阿里云的PFX证书 阿里云推荐Tomcat配置如下 <Connector port=" ...