Mr. Kitayuta's Colorful Graph

算法:根号分治。

题目大意先说一下:给一个 \(n\) 点 \(m\) 边的无向图,边有颜色。\(q\) 组询问,每次给出 \(u,v\),求有多少种颜色 \(c\),使得存在一条 \(u\) 到 \(v\) 的路径,这个路径中每条边的颜色都为 \(c\)。

数据范围:\(2\le n\le 10^5,1\le c\le m,q\le 10^5\)。

先考虑一个朴素的暴力,暴力对每个颜色加边,用并查集判连通性,暴力扫过每个询问,如果在一个颜色上这两个点是连通的,答案加 \(1\)。

发现这种做法在颜色非常多的时候要扫过每个颜色和每个询问的时间复杂度非常高,难以接受,所以要考虑优化。

我们怎么优化?上文提及了在颜色非常多的时候复杂度会爆炸,那么他有什么优势?当然是在颜色少的时候跑得很快,那么我们采取他的优势,想一想颜色多的时候的优秀的写法。

这里可以停顿 \(1\) 分钟,自己想一下。

我们可以发现,既然颜色多,边的数量不会太多,那么就证明每个颜色的边连接的点不会太多,所以我们可以暴力枚举这样的颜色的边连接的点,判断是否连通,如果连通就答案加 \(1\)。

但是会出现一个问题,如果这个点对不在询问里怎么办?这其实是无关紧要的,因为询问的我们会处理到,没有询问的随便加也不会影响。

所以我们记颜色 \(c\) 的边数为 \(cnt_c\),以 \(\sqrt m\) 为分界线,判断使用哪种暴力。

由于这道题的代码作者认为并不好写,所以下面放一下代码。

#include<bits/stdc++.h>
#define int long long
#define N 100005
#define pii pair<int,int>
#define x first
#define y second
using namespace std;
int n,m,q,cnt[N];
int p[N];
vector<pii>e[N],qry,rqry,f[N];
map<int,bool>col;
map<pii,int>res;
int find(int x){
if(p[x]!=x)p[x]=find(p[x]);
return p[x];
}
void force1(){
for(int i=1;i<=n;i++){
p[i]=i;
}
for(auto eu:col){
int c=eu.x;
if(cnt[c]<sqrt(m))continue;
for(auto edge:e[c]){
int a=edge.x,b=edge.y;
int fa=find(a),fb=find(b);
if(fa!=fb){
p[fa]=fb;
}
}
map<pii,bool>st;
for(auto eu:qry){
int a=eu.x,b=eu.y;
if(st[{a,b}])continue;
int fa=find(a),fb=find(b);
if(fa==fb)res[{a,b}]++;
st[{a,b}]=1;
}
for(auto color:e[c]){
int a=color.x,b=color.y;
p[a]=a;p[b]=b;
}
}
}
void force2(){
for(int i=1;i<=n;i++){
p[i]=i;
}
for(auto eu:col){
int c=eu.x;
if(cnt[c]>=sqrt(m))continue;
vector<int>ind;
map<int,bool>state;
for(auto edge:e[c]){
int a=edge.x,b=edge.y;
if(!state[a]){
state[a]=1;
ind.push_back(a);
}
if(!state[b]){
state[b]=1;
ind.push_back(b);
}
int fa=find(a),fb=find(b);
if(fa!=fb){
p[fa]=fb;
}
}
for(int i=0;i<ind.size();i++){
for(int j=i+1;j<ind.size();j++){
int a=ind[i],b=ind[j];
int c=min(a,b),d=max(a,b);
int fa=find(c),fb=find(d);
if(fa==fb){
res[{c,d}]++;
}
}
}
for(auto color:e[c]){
int a=color.x,b=color.y;
p[a]=a;p[b]=b;
}
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++){
int a,b,c;
cin>>a>>b>>c;
if(a>b)swap(a,b);
cnt[c]++;
col[c]=1;
e[c].push_back({a,b});
}
cin>>q;
for(int i=1;i<=q;i++){
int a,b;
cin>>a>>b;
if(a>b)swap(a,b);
qry.push_back({a,b});
rqry.push_back({a,b});
}
sort(qry.begin(),qry.end());
qry.erase(unique(qry.begin(),qry.end()),qry.end());
force1();
force2();
for(auto eu:rqry){
int a=eu.x,b=eu.y;
cout<<res[{a,b}]<<'\n';
}
return 0;
}

CF506D题解的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

  10. JSOI2016R3 瞎BB题解

    题意请看absi大爷的blog http://absi2011.is-programmer.com/posts/200920.html http://absi2011.is-programmer.co ...

随机推荐

  1. 博客更换新域名为52ecy.cn

    Tips:当你看到这个提示的时候,说明当前的文章是由原emlog博客系统搬迁至此的,文章发布时间已过于久远,编排和内容不一定完整,还请谅解` 博客更换新域名为52ecy.cn 日期:2017-10-2 ...

  2. 「C++」复杂模拟【壹】

    建议开启目录食用 阅读本文之前建议您先看这里,如果您已经看完了,那么就可以放心大胆的学习本文了. 我认为其实本文的难度还是比较大的,今天我们题是来自山东省省选,所以建议大家谨慎阅读,如果您是专业程序员 ...

  3. 利用Vue做一个小购物车

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  4. hbase第一课:hbase-2.2.7分布式搭建

    hbase-2.2.7分布式搭建文档 1.上传解压配置环境变量 # 1.解压 tar -xvf hbase-2.2.7-bin.tar.gz.gz # 2.配置环境变量 vim /etc/profil ...

  5. Ubuntu20.04之Nvidia驱动安装

    参考:https://blog.csdn.net/xiaokedou_hust/article/details/82187860,实际操作时和该博文有些出入,故作优化. s1.连接wifi,打开终端. ...

  6. Linux 特权 SUID/SGID 的详解

    导航 0 前言 1 权限匹配流程 2 五种身份变化 3 有效用户/组 4 特权对 Shell 脚本无效 5 Sudo 与 SUID/SGID 的优先级 6 SUID.SGID.Sticky 各自的功能 ...

  7. React Context 的使用

    使用React开发应用程序时,如果多个组件需要共享数据,可以把数据放到父组件中,通过属性向下传递给子组件.但当组件嵌套较深时,两个最底层的组件要想共享数据,那就霜要把数据放到最顶层的组件中,然后再一层 ...

  8. Yaml配置文件语法详解

    YAML 简介 YAML,即 "YAML Ain't a Markup Language"(YAML 不是一种标记语言)的递归缩写,YAML 意思其实是" Yet Ano ...

  9. 解决方案 | AutoCAD二次开发的ProgID一览表(AutoCAD2004 ~ AutoCAD2024)

    1 图片版本 2 文字版本 AutoCAD产品名 版本号 ProgID AutoCAD 2004 R16 AutoCAD.Application.16 AutoCAD 2005 R16.1 AutoC ...

  10. Django DRF @action 装饰器

    @action 装饰器在Django REST Framework (DRF) 中非常有用,它可以帮助你在ViewSet中创建自定义的动作,而不仅仅是依赖标准的CRUD操作(Create, Read, ...