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;
}

猜你喜欢

转载自www.cnblogs.com/sevenyuanluo/p/10076109.html
今日推荐