题目链接:

https://codeforces.com/contest/1166/problem/F

题意:

给出节点数为$n$,边数为$m$的图,保证每个点对都是互连的

定义彩虹路:这条路经过$k$个节点,对于$x(x\%2=0)$节点,的左右两条边颜色相同

现在有$q$次操作

第一种操作是添加一条边

第二种操作是回答是否能经过彩虹边从$a$节点到达$b$节点

数据范围:

$2 \le n \le 10^5$
$1 \le m,q \le 10^5$

分析:

我们可以考虑用并查集把那些可以互相到达(经过边数为偶数的彩虹路)的点对用并查集连接起来

当$a-b-c$的边的颜色相同时,我们把a和c节点用并查集连接起来,代表$a$和$c$互连

对于节点a,每个颜色的边只需要保存一条,这样可以快速合并节点

这样,两个点是否能到达,只需要判断他们的并查集根是不是相同

但是还有一种情况,$x$节点到$y$节点经过的边数为奇数,这样最后一条边的颜色就不重要了

我们可以给每个并查集添加一个集合,集合里面的点直接连接某个并查集的点

连接两个并查集用到了启发式合并(整个合并操作复杂度为$O(nlgn)$)

ac代码:

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define pa pair<int,int>
using namespace std;
const int maxn=1e5+10;
const int maxm=5e6+10;
const ll mod=1e9+7;
map<int,int>ma[maxn];//对于节点a,每个颜色的边只需要保存一条
set<int>se[maxn];
int n,m,c,q,boss[maxn];
void inti()
{
for(int i=1;i<=n;i++)
boss[i]=i;
}
int fin(int x)
{
if(boss[x]==x)return x;
return boss[x]=fin(boss[x]);
}
void uni(int a,int b)
{
int v1=fin(a),v2=fin(b);
if(v1==v2)return;
if(se[v1].size()>se[v2].size())swap(v1,v2);//启发式合并关键
boss[v1]=v2;
for(auto i :se[v1])se[v2].insert(i);
se[v1].clear();
}
void add_edge()
{
int a,b,v;
scanf("%d %d %d",&a,&b,&v);
if(ma[a].count(v))
uni(ma[a][v],b);
else
ma[a][v]=b;
if(ma[b].count(v))
uni(ma[b][v],a);
else
ma[b][v]=a;
se[fin(a)].insert(b);
se[fin(b)].insert(a);
}
int main()
{
scanf("%d %d %d %d",&n,&m,&c,&q);
inti();
for(int i=1; i<=m; i++)
add_edge();
while(q--)
{
getchar();
if(getchar()=='?')
{
int fla=0,a,b;
scanf("%d %d",&a,&b);
int v=fin(a);
if(v==fin(b)||se[v].find(b)!=se[v].end())//同一个集合,或者不同集合,但是再走一条边能到
printf("Yes\n");
else
printf("No\n");
}
else
{
add_edge();
}
}
return 0;
}

  

codeforces#1166F. Vicky's Delivery (Service并查集+启发式合并)的更多相关文章

  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. Codeforces 1166F 并查集 启发式合并

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

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

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

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

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

  8. 【AGC014E】Blue and Red Tree 并查集 启发式合并

    题目描述 有一棵\(n\)个点的树,最开始所有边都是蓝边.每次你可以选择一条全是蓝边的路径,删掉其中一条,再把这两个端点之间连一条红边.再给你一棵树,这棵树的所有边都是红边,问你最终能不能把原来的树变 ...

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

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

随机推荐

  1. Java装饰者模式(思维导图)

    图1 装饰者模式[点击查看图片] 1,一个简单的以人为主体的装饰者模式 被装饰者 public interface Human {//被装饰者 public void wearClothes(); p ...

  2. Linux环境下安装Nginx及其使用

    https://www.jb51.net/article/136161.htm 一.查看CentOS的版本 ? 1 cat /etc/redhat-release 二.添加资源库 在 CentOS 系 ...

  3. SIP 3pcc

    3PCC全称Third Party Call Control,中文即第三方电话呼叫控制,指的是由第三方控制者在另外两者之间建立一个会话,由控制者负责会话双方的媒体协商.3PCC是一种非常灵活的会话控制 ...

  4. JS ES6

    变量 let 块级作用域内有效 不能重复声明 不会预处理,不存在提升 var btns = document.getElementsByTagName('button'); for (let i = ...

  5. easyUI 布局

    Layout(布局) 布局容器有5个区域:北.南.东.西和中间.中间区域面板是必须的,边缘的面板都是可选的. 每个边缘区域面板都可以通过拖拽其边框改变大小,也可以点击折叠按钮将面板折叠起来.布局可以进 ...

  6. drone 更新仓库为truested

    drone 更新仓库为truested drone repo update -trusted=true my_org/repository DRONE_USER_CREATE=username:oct ...

  7. 解决Ubuntu下ssh无法启动

    Ubuntu  ssh一直无法启动. 通过 systemctl status ssh.service  查看到的错误是 Dec 16 13:35:22 iZm5eckxl2tqyka9eoe7b3Z ...

  8. LoadRunner(8)

    一.脚本关联技术  引入: 打开WebTours首页,点击administration连接: 具有大量管理项,LR为了模拟一些特效设置的选项,实际项目中不存在. -> 选择第三项: Set LO ...

  9. FFmpeg常用命令学习笔记(二)录制命令

    录制命令 1.FFmpeg录屏命令 ffmpeg -f avfoundation -i 1 -r 30 out.yuv -f:指定使用avfoundation采集数据 -i:指定从哪采集数据,它是一个 ...

  10. Mariadb多实例启动脚本

    #!/bin/bash port=3306 mysql_user="root" mysql_pwd="centos" cmd_path="/app/m ...