洛谷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;
}
posted @ 2020-02-21 11:56  quanjun  阅读(139)  评论(0编辑  收藏  举报