[BZOJ]1370 Gang团伙 镜像并查集

1370: [Baltic2003]Gang团伙

Time Limit: 2 Sec   Memory Limit: 64 MB
Submit: 772   Solved: 424
[ Submit][ Status][ Discuss]

Description

在某城市里住着n个人,任何两个认识的人不是朋友就是敌人,而且满足: 1、 我朋友的朋友是我的朋友; 2、 我敌人的敌人是我的朋友; 所有是朋友的人组成一个团伙。告诉你关于这n个人的m条信息,即某两个人是朋友,或者某两个人是敌人,请你编写一个程序,计算出这个城市最多可能有多少个团伙?

Input

第1行为n和m,N小于1000,M小于5000; 以下m行,每行为p x y,p的值为0或1,p为0时,表示x和y是朋友,p为1时,表示x和y是敌人。

Output

一个整数,表示这n个人最多可能有几个团伙。

Sample Input

6
4
E 1 4
F 3 5
F 4 6
E 1 2

Sample Output

3

HINT

{1},{2,4,6},{3,5}

Source

[ Submit][ Status][ Discuss]


HOME Back

很简单的并查集, 因为有敌人或朋友两种种类, 自然而然的想到拆点.

如果a和b是朋友的话, 就把a和b分别的集合合并: 

如果是敌人的话, 那么就把a 和 b + n, a + n 和 b分别的集合合并. 什么意思呢? 因为敌人的敌人是朋友, 所以我们对于某点a, 设一个镜像一般的点a+n, a+n所在的并查集就是a的敌人的并查集, 所以a 和 b + n合并, 满足敌人的敌人是朋友(b+n是b的敌人的集合). a + n 和 b合并同理. 最后处理一遍有多少个集合就可以了.

#include<stdio.h>
const int maxn = 2005;
char ch[1];
bool vis[maxn];
int fa[maxn], ans, n, m;
inline const int read(){
	register int x = 0;
	register char ch = getchar();
	while(ch < '0' || ch > '9') ch = getchar();
	while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
	return x;
}
int find(int x) { return (fa[x] == x) ? x : fa[x] = find(fa[x]);}
int main(){
	n = read(), m = read();
	for(int i = 1; i <= 2 * n; ++i) fa[i] = i;
	for(int i = 1; i <= m; ++i){
		scanf("%s", ch);
		int x = read(), y = read();
		if(ch[0] == 'E') fa[find(x)] = find(y + n), fa[find(x + n)] = find(y); 
		else fa[find(x)] = find(y);
	}
	for(int i = 1; i <= n; ++i) vis[find(i)] = true;
	for(int i = 1; i <= 2 * n; ++i) if(vis[i]) ans++;
	printf("%d\n", ans);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值