专栏文章

P10778 BZOJ3569 DZY Loves Chinese II 题解

P10778题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mipepi2o
此快照首次捕获于
2025/12/03 10:47
3 个月前
此快照最后确认于
2025/12/03 10:47
3 个月前
查看原文

前置知识

线性基 | 异或哈希

解法

强制在线限制了 luogu P5227 [AHOI2013] 连通图 的线段树分治无法通过。
注意到对于原图的一张生成树中的树边,如果它与覆盖它的返祖边都断开了就会变得不连通。
不妨考虑异或哈希,对返祖边随机赋权,树边的权值为覆盖它的返祖边的权值的异或和。询问时通过线性基判断能否正确插入来得到是否同时出现。
值得一提的是异或哈希能通过的重要限制是 k15k \le 15,即每次删的边不会太多。但是随着 kk 的增长,错误性会逐渐扩大,且当 k>O(logV)k> O(\log V) 后一定存在不能插入的情况(已经插满了)使得判断错误。

代码

CPP
#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define ull unsigned long long
#define sort stable_sort 
#define endl '\n'
mt19937_64 rng(random_device{}());
struct node
{
	int nxt,to,id;
}e[1000010];
int head[500010],u[500010],v[500010],vis[500010],ins[500010],cnt=0;
ull w[500010];
void add(int u,int v,int id)
{
	cnt++;  e[cnt]=(node){head[u],v,id};  head[u]=cnt;
}
void dfs(int x,int fa)
{
	vis[x]=ins[x]=1;
	for(int i=head[x];i!=0;i=e[i].nxt)
	{
		if(e[i].id!=fa)
		{
			if(vis[e[i].to]==0)  dfs(e[i].to,e[i].id);
			else  if(ins[e[i].to]==1)  w[e[i].id]=rng();
			w[fa]^=w[e[i].id];
		}
	}
	ins[x]=0;
}
struct Liner_Base
{
	ull d[70];
	void clear()
	{
		memset(d,0,sizeof(d));
	}
	int insert(ull x)
	{
		for(int i=63;i>=0;i--)
		{
			if((x>>i)&1)
			{
				if(d[i]==0)
				{
					d[i]=x;
					return 1;
				}
				x^=d[i];
			}
		}
		return 0;
	}
}L;
int main()
{
// #define Isaac
#ifdef Isaac
	freopen("in.in","r",stdin);
	freopen("out.out","w",stdout);
#endif
	int n,m,q,k,x,ans=0,flag,i,j;
	scanf("%d%d",&n,&m);
	for(i=1;i<=m;i++)
	{
		scanf("%d%d",&u[i],&v[i]);
		add(u[i],v[i],i);  add(v[i],u[i],i);
	}
	dfs(1,0);
	scanf("%d",&q);
	for(i=1;i<=q;i++)
	{
		scanf("%d",&k);  L.clear();
		flag=1;
		for(j=1;j<=k;j++)
		{
			scanf("%d",&x);  x^=ans;
			flag&=L.insert(w[x]);
		}
		ans+=flag;
		if(flag==0)  printf("Disconnected\n");
		else  printf("Connected\n");
	}
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...