BZOJ 1370 Baltic2003 Gang团伙 并查集

题目大意:给定n个人,朋友的朋友是朋友,敌人的敌人是朋友,朋友之间组成一个团伙,求团伙数

将每个点x拆成两个:x和x+n

如果x和y是朋友,就将x和y合并

如果x和y是敌人,就将x和y+n合并,将y和x+n合并

注意敌人的朋友不一定是敌人,因此如果x和y是朋友,不能将x+n和y+n合并

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 1010
using namespace std;
int n,m,ans,a[M];
namespace Union_Find_Set{
	int fa[M<<1];
	int Find(int x)
	{
		if(!fa[x]||fa[x]==x)
			return fa[x]=x;
		return fa[x]=Find(fa[x]);
	}
	void Union(int x,int y)
	{
		x=Find(x);y=Find(y);
		if(x==y) return ;
		fa[x]=y;
	}
}
int main()
{
	using namespace Union_Find_Set;
	int i,x,y;
	char p[10];
	cin>>n>>m;
	for(i=1;i<=m;i++)
	{
		scanf("%s%d%d",p,&x,&y);
		if(p[0]=='F')
			Union(x,y);//Union(x+n,y+n);
		else
			Union(x,y+n),Union(x+n,y);
	}
	for(i=1;i<=n;i++)
		a[i]=Find(i);
	sort(a+1,a+n+1);
	for(i=1;i<=n;i++)
		if(i==1||a[i]!=a[i-1])
			++ans;
	cout<<ans<<endl;
	return 0;
}
时间: 2024-10-12 04:30:41

BZOJ 1370 Baltic2003 Gang团伙 并查集的相关文章

BZOJ 1370: [Baltic2003]Gang团伙(luogu 1892)(种类并查集)

题面: bzoj题面有误,还是看luogu的吧 https://www.luogu.org/problemnew/show/P1892 题解: 种类并查集.. 因为有敌人的敌人是朋友这个条件,所以需要一个中转点.. 因此,将每个点拆成两个点,一个是朋友点,另一个是敌人点.当读到A与B是朋友时,就将A与B所对应的朋友点并集:当读到两个点是敌人的时候,就将A点所对应的敌人点与B所对应的朋友点并集,将A所对应的朋友点和B所对应的敌人点并集. 代码: #include<bits/stdc++.h> u

BZOJ 3562: [SHOI2014]神奇化合物 并查集+dfs

点击打开链接 注意到20w条边,但是询问只有1w,所以有很多边是从头到尾不变的. 首先离线处理,将从未删除的边缩点,缩点后的图的点数不会超过2w,对于每一次add或者delete,直接dfs看是否能从a走到b,然后维护一个ans. 数据不强,不然这种复杂度起码要跑10s.. #include<stdio.h> #include<iostream> #include<algorithm> #include<cstring> using namespace st

bzoj 2733 永无乡 - 并查集 - 线段树

永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛.如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b,则称岛 a 和岛 b 是连 通的.现在有两种操作:B x y 表示在岛 x 与岛 y 之间修建一座新桥.Q x k 表示询问当前与岛 x连通的所有岛中第 k 重要的是哪座岛,即所有与岛 x 连通的岛中重要度排名第 k 小的岛是哪 座,请你输

bzoj 2936 [Poi 1999] 降水 - 并查集

题目传送门 需要root权限的传送门 题目大意 有一个$n\times m$的网格图,每一格都有一个高度.一次降雨过后问最多能积多少水. 考虑算每一高度能储存的水的量. 如果小于等于这个高度的格子和边界连通,那么水就会流走,这一部分不能算入答案. 所以用并查集维护高度小于等于当前高度的格子的连通性.每次答案加已经找到的格子数目减去和边界连通的格子数. Code 1 /** 2 * bzoj 3 * Problem#2936 4 * Accepted 5 * Time: 56ms 6 * Memo

【BZOJ 3674】可持久化并查集加强版&amp;【BZOJ 3673】可持久化并查集 by zky 用可持久化线段树破之

最后还是去掉异或顺手A了3673,,, 并查集其实就是fa数组,我们只需要维护这个fa数组,用可持久化线段树就行啦 1:判断是否属于同一集合,我加了路径压缩. 2:直接把跟的值指向root[k]的值破之. 3:输出判断即可. 难者不会,会者不难,1h前我还在膜这道题,现在吗hhh就当支持下zky学长出的题了. 3673: #include<cstdio> #include<cstring> #include<algorithm> #define read(x) x=ge

bzoj1370 [Baltic2003]Gang团伙

题目链接 一道水题 把一个人分为两种人格:作为朋友时(i):作为敌人时(i+n) 拆点并查集维护关系 注意统计答案时要先find之后取个数而不是找fa[i]==i(1<=i<=n)的个数 因为一些人只作为敌人出现过所以find的结果可能是作为敌人的人格就统计不到,所以要先find 1 #include<algorithm> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5

BZOJ 1116 [POI2008]CLO(并查集)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1116 [题目大意] Byteotia城市有n个towns,m条双向roads.每条road连接两个不同的towns, 没有重复的road.你要把其中一些road变成单向边使得:每个town都有且只有一个入度 [题解] 我们发现当一个连通块边数大于等于其点数的时候就满足条件, 那么此题如果出现边数少于点数的连通块就不成立, 用并查集能够完成判断. [代码] #include <cstd

bzoj 1455 可并堆+并查集

一个堆和一个并查集对应,并且满足并查集中所有没有死的人等于堆中的人 1 /************************************************************** 2 Problem: 1455 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:2688 ms 7 Memory:32336 kb 8 *************************************************

【BZOJ】3673: 可持久化并查集 by zky &amp; 3674: 可持久化并查集加强版(可持久化线段树)

http://www.lydsy.com/JudgeOnline/problem.php?id=3674 http://www.lydsy.com/JudgeOnline/problem.php?id=3673 双倍经验啦啦啦.. 给主席树换了个名称果然高大上... 首先要可持久化并查集其实就是可持久化数组... 那么因为数组的形式是这样的$P[x]$,那么我们用一种数据结构实现查找x返回对应的$P[x]$即可啦啦啦. 然后那么我所学的可持久化目前只有主席树QAQ哪天去写写fhqtreap...