洛谷P1892 [BOI2003]团伙 题解 并查集
题目链接:https://www.luogu.com.cn/problem/P1892
题目大意:
告诉你一些朋友和敌人关系。
以及:
- 我朋友的朋友是我的朋友;
- 我敌人的敌人也是我的朋友。
求:最多有多少各团伙?
解题思路:
把每个点 \(i\) 拆分成两个点 \(i\) 和 \(i+n\),其中 \(i\) 和 \(i+n\) 是对应的敌对关系。
然后,
- 当 \(a\) 和 \(b\) 是朋友,则合并 \(a\) 与 \(b\);
- 当 \(a\) 和 \(b\) 是敌人,则合并 \(a\) 与 \(b+n\),合并 \(a+n\) 与 \(b\)。
实现代码如下:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 10010, maxm = maxn*2;
int n, m, f[maxn], cnt;
bool vis[maxn];
string s;
void init() {
for (int i = 1; i <= 2*n; i ++) f[i] = i;
}
int Find(int x) {
return x == f[x] ? x : f[x] = Find(f[x]);
}
void Union(int x, int y) {
int a = Find(x), b = Find(y);
f[a] = f[b] = f[x] = f[y] = min(a, b);
}
int main() {
cin >> n >> m;
init();
while (m --) {
int a, b;
cin >> s >> a >> b;
if (s[0] == 'F') Union(a, b);
else Union(a+n, b), Union(a, b+n);
}
for (int i = 1; i <= n; i ++) {
if (!vis[Find(i)]) {
vis[Find(i)] = true;
cnt ++;
}
}
cout << cnt << endl;
return 0;
}