1. 程式人生 > >luogu P1892 [BOI2003]團伙

luogu P1892 [BOI2003]團伙

(在機房寫的題解就沒辦法放題目了www

(只能放連結  orz

emmmmm

是一道(蠻簡單的  並查集

就是如何記錄朋友或敵人的關係

題解裡有一個反集的思想非常有意思(其實是我好不容易才理解23333

我們拿樣例為例看一下吧

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

反集的實現過程是這樣的

 if(ch == 'E'){
      fa[get(p + n)] = get(q);
      fa[get(q + n)] = get(p);
    }

首先 f[7] = 4;
然後正常的並集 f[3] = 5  f[4] = 6

再次 f[get(7)] = 2

此時get(7) = 4

那麼 f[4] = 2

此時 2,4,6 為一個團伙

3,5 為一個團伙

1 單獨一人

總共 3 個團伙

反集太精彩了!!!

那麼上程式碼

#include<cstdio>
#include<iostream>
using namespace std;
#define maxn 1010
#define maxm 5010

int fa[maxn],w[maxm];

int get(int x){
  if(fa[x] == x)return x;
  else return fa[x] = get
(fa[x]); } int main(){ int n,m; scanf("%d%d",&n,&m); for(int i = 1;i <= n * 2;i++) fa[i] = i; for(int i = 1;i <= m;i++){ char ch; int p,q; cin >> ch >> p >> q; if(ch == 'F') fa[get(p)] = fa[get(q)]; if(ch == 'E'){ fa[get(p + n)] = get
(q); fa[get(q + n)] = get(p); } } int ans = 0; for(int i = 1;i <= n;i++) if(fa[i] == i)//看有幾個根即為有幾個團伙 ans++; printf("%d",ans); return 0; }