zoukankan      html  css  js  c++  java
  • 洛谷 P1892 [BOI2003]团伙(并查集)

    嗯...

     

    题目链接:https://www.luogu.org/problemnew/show/P1892

     

    通过读题可以很清楚的发现这是一个并查集的题,并且要有两个集合:

    若他们p和q是朋友,则存入第一个集合;若他们是敌人,则存入第二个集合——即反集(很模糊的一个东西

    因为最多只有n个数,所以我们将f数组一分为二,f [1] ~ f [n] 为第一个集合, f [n+1] ~ f [n + n] 为反集,然后根据题意进行并查集的基本操作即可...

    本题细节:

    (1) 注意读题,最后要求的一共有多少个团伙(即我们合并后一共有多少个父亲), 我们只需要从1 for 到 n,如果f [i] == i,ans++即可。

    (2) 注意我们在f 数组中存了两个集合,会用到2 * n,所以在初始化f 数组的时候需要从1 for 到 2 * n。

    (3) c,p,q的读入只能使用cin, scanf会爆掉。

    (4) 第一个集合(p和q为朋友)直接合并即可,而反集的合并需要两次合并。(只能这么理解吧...详见代码

    (5) 注意反集时find函数中的参数,而不是在find函数外再加n。

     

    AC代码:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 
     5 using namespace std;
     6 
     7 int f[10005], ans;
     8 int n, m, p, q;
     9 char c;
    10 
    11 inline int find(int x){
    12     if(f[x] != x)
    13         f[x] = find(f[x]);
    14     return f[x];
    15 }
    16 
    17 int main(){
    18     scanf("%d%d", &n, &m);
    19     for(int i = 1; i <= n * 2; i++)//注意两倍 
    20         f[i] = i;
    21     for(int i = 1; i <= m; i++){
    22         cin >> c >> p >> q;
    23         if(c == 'F'){
    24             f[find(p)] = find(q);//是朋友直接合并 
    25         }
    26         if(c == 'E'){
    27             f[find(p + n)] = find(q);//反集合并两次,注意在find函数中的参数 
    28             f[find(q + n)] = find(p);
    29         }
    30     }
    31     for(int i = 1; i <= n; i++){
    32         if(f[i] == i) ans++;//自己为根节点的个数,即集团个数 
    33     }
    34     printf("%d", ans);
    35     return 0;
    36 }
    AC代码
  • 相关阅读:
    适配器模式
    自己DIY word2010脚注和尾注没有的格式
    Linux单网卡,双IP,双网关配置,并搭建squid proxy上网
    about using gnuplot
    ReadDirectoryChangesW 函数 流沙
    Jquery easyui 异步树 流沙
    Overlapped I/O 学习 流沙
    jQuery.get(url,[data],[callback]) 流沙
    MsgWaitForMultipleObjectsEx用法 流沙
    Oracle smon_scn_time 表 说明
  • 原文地址:https://www.cnblogs.com/New-ljx/p/10883425.html
Copyright © 2011-2022 走看看