扩展域并查集Codeforces Round #747 (Div. 2) D. The Number of Imposters

Posted 行码棋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了扩展域并查集Codeforces Round #747 (Div. 2) D. The Number of Imposters相关的知识,希望对你有一定的参考价值。

题目链接:
https://codeforces.com/problemset/problem/1594/D

有 n 个人,每个人可能是诚实的人或者说谎的人。
诚实的人永远说真话,说谎的人永远说假话。
有 m 个条件,分别表示 i 说 j 是诚实的人/说谎的人。
你需要判断在这些限制条件下,最多有可能有几个诚实的人,或输出 -1 声明不可能存在这种情况。


分析规则:

  • 若A说B诚实,则AB要么都诚实,要么都是骗子
  • 若A说B骗子,则A诚实B骗子 ,或者A骗子B诚实

可以发现当一个人诚实和骗子确定下来,与他相关的人都会确定下来。

考虑用一个并查集进行维护,并查集开两倍的空间。

x表示表示一个人,则x表示他诚实,x + n表示他是骗子。所以并查集前半部分的空间开的是诚实的人的,后半部分开的是骗子的人的。

注意: 初始化时,只有前半部分的人的sz数组初始化为1,其余都为0

如果 f i n d ( x ) = = f i n d ( x + n ) find(x)==find(x+n) find(x)==find(x+n),则会产生冲突,结果为-1


并查集中因为一正一反,如果有两种情况,那么这两种情况是相反的。用个图来理解

#include<bits/stdc++.h>
using namespace std;
using ll = long long; 
using pii = pair<int, int>;
const int N = 1e5 + 5;

struct dsu

	vector<int> f, sz;
	dsu(int n)
	
		f.resize(n);
		sz.resize(n, 1);
 		for(int i = 1; i < n; i++) f[i] = i;
	
	int find(int x)
	
		return x == f[x] ? x : f[x] = find(f[x]);
	
	void merge(int x, int y)
	
		x = find(x);
		y = find(y);
		if(x == y) return;
		if(sz[x] < sz[y])  swap(x, y);
		f[y] = x;
		sz[x] += sz[y];
		sz[y] = 0;
	
	
;
void solve()

	int n, m;
	cin >> n >> m;
	
	dsu tr(2 * n + 1);
	for(int i = n + 1; i <= 2 * n; i++)
		tr.sz[i] = 0;
	for(int i =1; i <= m; i++)
	
		int x, y;
		string s;
		cin >> x >> y >> s;
		if(s[0] == 'c') tr.merge(x, y), tr.merge(x + n, y + n);
		else tr.merge(x, y + n), tr.merge(x + n, y);
	
	
	int res = 0;
	for(int i = 1; i <= n; i++)
	
		int x = tr.find(i), y = tr.find(i + n);
		if(x == y) 
		
			cout << -1 << "\\n";
			return;
		
		res += max(tr.sz[x], tr.sz[y]);
		tr.sz[x] = 0, tr.sz[y] = 0;
	
	cout << res << "\\n";

int main()

	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int t;
	cin >> t;
	while(t--) solve();
	return 0;

以上是关于扩展域并查集Codeforces Round #747 (Div. 2) D. The Number of Imposters的主要内容,如果未能解决你的问题,请参考以下文章

扩展域并查集

[数据结构总结] 扩展域并查集

力扣 每日一题 886. 可能的二分法难度:中等,rating: 1794(并查集 / 拆点优化的扩展域并查集)

poj1733 Parity Game(扩展域并查集)

POJ2912 Rochambeau [扩展域并查集]

P1525 关押罪犯扩展域并查集