洛谷 P1892 [BOI2003] 团伙 种类并查集 扩展域并查集
种类并查集!!!!
存敌人
主要要理解敌人的敌人就是朋友这句话,我们就可以用并查集来维护朋友,用一个数组来储存他的其中一个敌人,后面遇到其他他的敌人时,将他的敌人用并查集连起来成为朋友。
注意这题要你输出团队数而不是团队的人数不会就我这么唐吧。
#include <bits/stdc++.h>
using namespace std;
const int N=1005;
int n,m;
int fa[N];
int a[N];
int find(int x){
return fa[x]==x?x:find(fa[x]);
}
void add(int u,int v){
int x=find(u);
int y=find(v);
fa[x]=y;
}
int cnt[1005];
int ans;
int main(){
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=n;i++){
fa[i]=i;
}
for(int i=1;i<=m;i++){
char c;
int u,v;
cin>>c>>u>>v;
if(c=='F'){
add(u,v);
}
else{
if(!a[u]){
a[u]=v;
}
else{
add(a[u],v);
}
if(!a[v]){
a[v]=u;
}
else{
add(a[v],u);
}
}
}
for(int i=1;i<=n;i++){
if(fa[i]==i){
ans++;
}
}
cout<<ans;
return 0;
}
反集
当然这题的方法开两倍空间进行维护,或者说叫反集。
#include <bits/stdc++.h>
using namespace std;
const int N=2005;
int n,m;
int fa[N];
int find(int x){
return fa[x]==x?x:find(fa[x]);
}
void add(int u,int v){
int x=find(u);
int y=find(v);
fa[x]=y;
}
int ans;
int main(){
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=n*2;i++){
fa[i]=i;
}
for(int i=1;i<=m;i++){
char c;
int u,v;
cin>>c>>u>>v;
if(c=='F'){
add(u,v);
}
else{
add(u+n,v);
add(v+n,u);
}
}
for(int i=1;i<=n;i++){
if(fa[i]==i){
ans++;
}
}
cout<<ans;
return 0;
}