浅谈扩展域并查集之种类并查集
[NOIP2010 提高组] 关押罪犯
考虑用并查集维护两个监狱里面的情况。首先对于 \([1,n]\) 我们表示为 \(A\) 监狱里面的情况,对于 \([n+1,2n]\) 我们表示为 \(B\) 监狱里面的情况,首先这两个监狱里面的情况是镜像的,因为你不确定也不需要确定哪个人到底去了哪个监狱,所以存镜像的表示关系就好了。
那么就很显然了,我们贪心排好序后直接交叉合并,如果出现冲突就直接输出并跳出即可。
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int ans=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)){ans=(ans<<3)+(ans<<1)+ch-48;ch=getchar();}
return ans*f;
}
const int N=1e5+5;
int n,m;
int fa[N<<1];
int find(int x){
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
struct lzk{
int u,v,c;
}node[N];
bool cmp(lzk x,lzk y){
return x.c>y.c;
}
int main(){
n=read(),m=read();
for(int i=1;i<=n<<1;i++) fa[i]=i;
for(int i=1;i<=m;i++) node[i].u=read(),node[i].v=read(),node[i].c=read();
sort(node+1,node+1+m,cmp);
for(int i=1;i<=m;i++){
int x1=find(node[i].u),y1=find(node[i].v);
int x2=find(node[i].u+n),y2=find(node[i].v+n);
if(x1==y1||x2==y2) return printf("%d",node[i].c),0;
fa[x1]=y2;
fa[x2]=y1;
}
printf("0");
return 0;
}
[NOI2001] 食物链
这题也可以用到种类并查集,我们只需要开 \(3\) 倍的空间,\([1,n]\) 表示 \(A\) 类,\([n+1,2n]\) 表示 \(B\) 类,\([2n+1,3n]\) 表示 \(C\) 类。同样这也满足镜像的性质(也许是种类并查集的性质?),所以我们只用讨论一种即可。
- 对于操作 \(1\),我们只用把同类的 \(x,y\) 合并就好了,如果出现 \(x,y\) 不同类的属于同一个集合,那么就意味着 \(x,y\) 有捕食关系就是假话;
- 对于操作 \(2\),我们根据题目所给的 \(A\) 吃 \(B\),\(B\) 吃 \(C\),\(C\) 吃 \(A\) 的顺序合并即可,如果出现 \(x,y\) 属于同一类的同一个集合或者 \(y\) 吃 \(x\) 的情况,就是假话。
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int ans=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)){ans=(ans<<3)+(ans<<1)+ch-48;ch=getchar();}
return ans*f;
}
const int N=1e5+5;
int n,m;
int cnt;
int fa[N*3];
int find(int x){
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
int main(){
n=read(),m=read();
for(int i=1;i<=n*3;i++) fa[i]=i;
for(int i=1;i<=m;i++){
int opt=read(),x=read(),y=read();
if(x>n||y>n){cnt++;continue;}
if(opt==1){
int x1=find(x),y1=find(y);
int x2=find(x+n),y2=find(y+n);
int x3=find(x+(n<<1)),y3=find(y+(n<<1));
if(x1==y2||x1==y3){cnt++;continue;}
fa[x1]=y1;
fa[x2]=y2;
fa[x3]=y3;
}
else{
int x1=find(x),y1=find(y);
int x2=find(x+n),y2=find(y+n);
int x3=find(x+(n<<1)),y3=find(y+(n<<1));
if(x1==y1||x2==y1){cnt++;continue;}
fa[x1]=y2;
fa[x2]=y3;
fa[x3]=y1;
}
}
printf("%d",cnt);
return 0;
}

浙公网安备 33010602011771号