洛谷 P1892 [BOI2003] 团伙 种类并查集 扩展域并查集

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; 
}
posted @ 2024-09-11 16:05  sad_lin  阅读(5)  评论(0编辑  收藏  举报