并查集 关于约翰和他的奶牛(不知道叫啥)C++题解

内存限制: 256 MiB 时间限制: 1000 ms 标准输入输出 题目类型: 传统 评测方式: 文本比较

题目描述

在长时间与他的奶牛相处之后,农夫约翰已经开始理解他们的语言了。而且他注意到,在他的 N 头奶牛中(2 <= N <= 1000),有一些总是说实话,而另一些则总是说谎。

农夫约翰仔细听取了他的奶牛们的 M 条陈述(1 <= M <= 10,000),每条陈述都是“x y T”的形式,意思是“奶牛 x 声称奶牛 y 总是说实话”,或者是“x y L”的形式,意味着“奶牛 x 声称奶牛 y 总是说谎”。每个陈述都涉及一对不同的奶牛,同一对奶牛可能在多个陈述中出现。

不幸的是,农夫约翰相信他可能把清单上的一些条目记错了,所以可能没有一种有效的方法来指定每头奶牛是说实话的人还是说谎的人,能与约翰名单上的所有 M 条陈述保持一致。为了帮助约翰尽可能多地保留他的列表,请计算出最大的 A 值,使得存在一个有效的方式来指定每头奶牛是说实话的人还是说谎的人,并且与约翰列表上的前 A 项记录保持一致。

输入格式

第 1 行:两个由空格分隔的整数 N 和 M。

第 2..1+M 行:每行的格式为“x y L”或“x y T”,描述了奶牛 x 关于奶牛 y 的陈述。

输出格式

第 1 行:最大的 A 值,使得约翰名单上的前 A 项可以与对 N 头奶牛进行的“说实话者”或“说谎者”的某些分配保持一致。

样例

输入样例
复制4 3
1 4 L
2 3 T
4 1 T
输出样例
复制2
样例说明

有 4 头奶牛和 3 条陈述。奶牛 1 说奶牛 4 在说谎,奶牛 2 说奶牛 3 在说实话,奶牛 4 说奶牛 1 在说实话。

陈述 1 和 3 不能同时被满足,但是陈述 1 和 2 可以同时被满足,如果我们让奶牛 1 到 3 告诉实话,而奶牛 4 说谎。
 

#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 5;
int n, m, ans;
int Max = INT_MIN;
int parent[2 * N]; 
void init(int n) {
	for(int i = 1; i <= 2 * n; i++) parent[i] = i;
} 
int find(int x) {
	if(x == parent[x]) return x;
	return parent[x] = find(parent[x]);
} 
void uni(int x, int y) {
	int p = find(x), q = find(y);
	if(p == q) return;
	parent[q] = p;
} 
signed main() {
	scanf("%d %d", &n, &m);
	init(n);
	for(int x, y, i = 1; i <= m; i++) {
		char c;
		cin >> x >> y >> c;
		if(c == 'T') {
			if(find(x + n) == find(y)) {
				Max = max(Max, ans);
				break;
			} 
			ans++;
			uni(x, y), uni(x + n, y + n);
		} else if(c == 'L') {
			if(find(x) == find(y)) {
				Max = max(Max, ans);
				break;
			} 
			ans++;
			uni(x, y + n), uni(y, x + n);
		} 
	} 
	if(Max == INT_MIN) printf("%d", m);
	else printf("%d", Max);
	return 0;
} 

一道普普通通的并查集

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值