题目链接

\(Description\)

给定\(d\)张无向图,每张图都有\(n\)个点。一开始,在任何一张图中都没有任何边。

接下来有\(m\)次操作,每次操作会给出\(a,b,k\),意为在第\(k\)张图中的点\(a\)和点\(b\)之间添加一条无向边。

你需要在每次操作之后输出有序数对\((a,b)\)的个数,满足\(1\leq a,b\leq n\),且\(a\)点和\(b\)点在\(d\)张图中都连通。

\(d\leq 200,n\leq 5000,m\leq 1000000\)

\(Solution\)

我们需要知道的只是每对点之间是否连通,即在同一张图所属的连通块是否一样

于是我们对每个点在d张图中所属的连通块标号进行哈希,这个哈希要能快速删除一个标号 插入一个标号

如果有两个点哈希后的值相同,那么这两个点在d张图中都连通。于是我们再对这个哈希值做一遍哈希,来计算相同哈希值的个数

连边时用启发式合并,每次将size小的连通块全部修改fa,总复杂度\(O(dn\log n)\)

//75500kb	4628ms
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
typedef unsigned long long ull;
const int N=5005,D=205,M=1e6+5,mod=2e6;
const ull seed=769; int n,m,d,H[D][N],Enum,to[M<<1],nxt[M<<1],fa[D][N],sz[D][N],Ans;
ull hs_id[N],Pow[D];
struct Hash_Table
{
int top,h_H[mod+5],sk[mod],h_nxt[mod],cnt[mod];
ull val[mod];
void Init()
{
top=mod-5;
for(int i=1; i<=top; ++i) sk[i]=i;
}
void Insert(ull x)
{
int p=x%mod;
for(int i=h_H[p]; i; i=h_nxt[i])
if(val[i]==x) {Ans+=2*cnt[i]+1,++cnt[i]; return;}
++Ans;//(a,a)也算一对
int pos=sk[top--];
val[pos]=x, cnt[pos]=1, h_nxt[pos]=h_H[p], h_H[p]=pos;
}
void Delete(ull x)
{
int p=x%mod,pre=h_H[p];
if(val[pre]==x)
{
Ans-=2*cnt[pre]-1;
if(!--cnt[pre]) sk[++top]=pre, h_H[p]=h_nxt[pre];
}
else
for(int i=h_nxt[pre]; i; pre=i,i=h_nxt[i])
if(val[i]==x)
{
Ans-=2*cnt[i]-1;
if(!--cnt[i]) sk[++top]=i, h_nxt[pre]=h_nxt[i];
break;
}
}
}hs2; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline void AddEdge(int u,int v,int k){
to[++Enum]=v, nxt[Enum]=H[k][u], H[k][u]=Enum;
}
void DFS(int x,int f,int k,int anc)
{
hs2.Delete(hs_id[x]);
hs_id[x]-=Pow[k]*fa[k][x];//fa就是belong了
fa[k][x]=anc;
hs_id[x]+=Pow[k]*anc;
hs2.Insert(hs_id[x]);
for(int i=H[k][x]; i; i=nxt[i])
if(to[i]!=f) DFS(to[i],x,k,anc);
}
void Union(int u,int v,int k)
{
if(fa[k][u]==fa[k][v]) return;
if(sz[k][fa[k][u]]<sz[k][fa[k][v]]) std::swap(u,v);
sz[k][fa[k][u]]+=sz[k][fa[k][v]];
DFS(v,u,k,fa[k][u]);
AddEdge(u,v,k),AddEdge(v,u,k);
} int main()
{
d=read(),n=read(),m=read();
Pow[0]=1;
for(int i=1; i<D; ++i) Pow[i]=Pow[i-1]*seed;
hs2.Init();
for(int i=1; i<=n; hs2.Insert(hs_id[i++]))
for(int j=1; j<=d; ++j)
fa[j][i]=i, sz[j][i]=1, hs_id[i]+=Pow[j]*i;//Hash = (∑s[i]seed^i) mod 2^{31}
int a,b,k;
while(m--)
a=read(),b=read(),k=read(),Union(a,b,k),printf("%d\n",Ans);
return 0;
}

BZOJ.4298.[ONTAK2015]Bajtocja(Hash 启发式合并)的更多相关文章

  1. bzoj 4298 [ONTAK2015]Bajtocja——哈希+启发式合并

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4298 题面: 给定d张无向图,每张图都有n个点.一开始,在任何一张图中都没有任何边.接下来有 ...

  2. @bzoj - 4298@ [ONTAK2015]Bajtocja

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定d张无向图,每张图都有n个点.一开始,在任何一张图中都没有任 ...

  3. BZOJ 2809: [Apio2012]dispatching( 平衡树 + 启发式合并 )

    枚举树上的每个结点做管理者, 贪心地取其子树中薪水较低的, 算出这个结点为管理者的满意度, 更新答案. 用平衡树+启发式合并, 时间复杂度为O(N log²N) ------------------- ...

  4. BZOJ 3545: [ONTAK2010]Peaks( BST + 启发式合并 + 并查集 )

    这道题很好想, 离线, 按询问的x排序从小到大, 然后用并查集维护连通性, 用平衡树维护连通块的山的权值, 合并就用启发式合并.时间复杂度的话, 排序是O(mlogm + qlogq), 启发式合并是 ...

  5. BZOJ 2888 资源运输(启发式合并LCT)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2888 [题目大意] 不断加边,问每个连通块的重心到其它点的距离和的和 [题解] 启发式 ...

  6. BZOJ 3545: [ONTAK2010]Peaks [Splay启发式合并]

    3545: [ONTAK2010]Peaks 题意:带权图,多组询问与一个点通过边权\(\le x\)的边连通的点中点权k大值 又读错题了,输出点一直WA,问的是点权啊 本题加强版强制在线了,那这道题 ...

  7. bzoj 1483: [HNOI2009]梦幻布丁 启发式合并vector

    1483: [HNOI2009]梦幻布丁 Time Limit: 10 Sec  Memory Limit: 64 MB[Submit][Status][Discuss] Description N个 ...

  8. BZOJ 1483 梦幻布丁(链表+启发式合并)

    给出一个长度为n的序列.支持两种操作: 1.把全部值为x的修改成y.2.询问序列有多少连续段. 我们可以对于每个值建立一个链表.对于操作1,则可以将两个链表合并. 对于操作2,只需要在每次合并链表的时 ...

  9. BZOJ 2733: [HNOI2012]永无乡 启发式合并treap

    2733: [HNOI2012]永无乡 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

随机推荐

  1. 程序执行的过程分析--【sky原创】

    程序执行的过程:     比如我们要执行3 + 2   程序计数器(PC) = 指令地址 指令寄存器(IR) = 正在执行的命令 累加器(AC) = 临时存储体   那么实际上执行了三条指令 每条指令 ...

  2. pt-online-schema-change VS oak-online-alter-table

    前言 在上篇文章中提到了MySQL 5.6 Online DDL,如果是MySQL 5.5的版本在DDL方面是要付出代价的,虽然已经有了Fast index Creation,但是在添加字段还是会锁表 ...

  3. 福利爬虫妹子图之获取种子url

    import os import uuid from lxml import html import aiofiles import logging from ruia import Spider, ...

  4. ES系列十八、FileBeat发送日志到logstash、ES、多个output过滤配置

    一.FileBeat基本概念 简单概述 最近在了解ELK做日志采集相关的内容,这篇文章主要讲解通过filebeat来实现日志的收集.日志采集的工具有很多种,如fluentd, flume, logst ...

  5. 使用 Virtual Machine Manager 管理虚拟机

    转载自https://www.ibm.com/developerworks/cn/cloud/library/cl-managingvms/   尽管服务器管理在过去问题重重,但虚拟化管理简化了一些问 ...

  6. pl sql 记住用户名密码

    tools--Preferences--Logon History 选择  “Store history”是默认勾选的,勾上“Store with password” 登录时从下拉框选择用户名则自动登 ...

  7. centos系统初始化脚本

    #!/bin/bash #检测是否为root用户 ];then echo "Must be root can do this." exit fi #检测网络 echo " ...

  8. centos6.5下java和tomcat环境部署

    软件包: tomcat安装包 apache-tomcat-7.0.67.zip jdk安装包 jdk-6u10-linux-x64.bin 下载地址:http://www.oracle.com/tec ...

  9. Idea xml 粘贴文本保持原有格式

    setting->Editor->Code Style->XML 在右边的面板中,单击第二个 “Other” 的页签,勾选“Keep white spaces”,重启idea.

  10. Pycharm4.5注册码 激活

    name : newasp ===== LICENSE BEGIN ===== 09086-12042010 00001EBwqd8wkmP2FM34Z05iXch1Ak KI0bAod8jkIffy ...