• 《洛谷深入浅出进阶篇》P1995 程序自动分析——并查集,离散化


    上链接:P1955 [NOI2015] 程序自动分析 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P1955

    上题干:

    首先给你一个整数t,代表t次操作。

    每一次操作包含以下内容:

    1.给你一个整数n,让你执行n次条件

    接下来n行,每行给你3个整数i,j,k,

    例如 1 2 1

    或  1 2 0

    (前面两个数代表下标,第三个整数k代表条件,如果它是1 ,则代表 x1 = x2,如果它是0,代表x1!=x2) 

    然后我们每一次操作需要输出yes 或 no 来表示这n个条件是否全部成立。

    (假如给出这样的数据:

        n=4

        1 2 1

        2 3 1

        1 4 1

        3 4 0

        第一个条件到第四个条件分别是 x1=x2,x2=x3,x1=x4 ,x3!=x4

    由于前面三个条件我们可以得知  x1=x2=x3=x4   所以与x3!=x4矛盾,输出no)

    数据 n<=1e6, i,j<=1e9

    很显然,这道题的条件和数据范围告诉我们:需要用到并查集+(离散化 or hash表)

    第一,并差集的特点就是能将不同的集合连接到一起,然后便于我们查询某两个元素是否为同一集合。

    第二,这道题的数据范围太大了,i能达到ie9,所以我们直接用并查集的话,毫无疑问,数组装不下。所以我们可以用离散化来大大缩小数据范围,除此之外呢,我们还可以用hash表来处理这样的大数据,使得每一个大数据都有一个特别的标记与之对应。

    这两种方法都满足我们的需求,这里主要用离散化来实现代码。

    还记得离散化的具体步骤吗?

    记录散点,排序,去重,二分查找

    并查集的具体步骤呢?

    初始化集合,建立查询函数,合并函数。

    所以我们的思路是这样的:

    1,先将每一次的散点都存入一个数组b中

    2,对这个数组b进行排序

    3,对这个数组进行去重(可以选择重新建立一个数组c来存放去重后的数据,也可以直接用unique函数。)

    4,二分查找每一对散点的相对位置。

    5,初始化并查集

    6,如果第三个数字k=1,我们就利用并查集来合并两个集合。

    7,如果第三个数字k=0,我们就查询两个数是否为同一集合,如果是同一集合,那么我们有

    上代码:

    1. const int MAXN = 1e6 + 10;
    2. struct st {
    3. int x, y, z;
    4. };
    5. st a[MAXN];//三组输入数据存放之处
    6. int b[2 * MAXN];// 存入散点
    7. int c[2 * MAXN];//排序数组
    8. int fa[2 * MAXN];//并查集
    9. int btop, ctop;
    10. int find1(int x)
    11. {
    12. if (x == fa[x])return fa[x];
    13. return fa[x] = find1(fa[x]);
    14. }
    15. void join1(int c1, int c2)
    16. {
    17. int f1 = find1(c1), f2 = find1(c2);
    18. if (f1 != f2)fa[f1] = f2;
    19. }
    20. int main()
    21. {
    22. int t;
    23. cin >> t;
    24. while (t--)
    25. {
    26. btop = 0;
    27. ctop = 0;
    28. int n;
    29. cin >> n;
    30. for (int i = 1; i <= n; i++)
    31. {
    32. cin >> a[i].x >> a[i].y >> a[i].z;
    33. b[++btop] = a[i].x;
    34. b[++btop] = a[i].y;
    35. }
    36. sort(b + 1, b + 1 + btop);
    37. for (int i = 1; i <= btop; i++)if (i == 1 or b[i] != b[i - 1])c[++ctop] = b[i];
    38. for (int i = 1; i <= n; i++)
    39. {
    40. a[i].x = lower_bound(c + 1, c + 1 + ctop, a[i].x) - c;
    41. a[i].y = lower_bound(c + 1, c + 1 + ctop, a[i].y) - c;
    42. }
    43. for (int i = 1; i <= ctop; i++)
    44. {
    45. fa[i] = i;
    46. }
    47. for (int i = 1; i <= n; i++)
    48. {
    49. if(a[i].z)
    50. join1(a[i].x, a[i].y);
    51. }
    52. bool fk = 1;
    53. for (int i = 1; i <= n; i++)
    54. {
    55. if (a[i].z==0)
    56. {
    57. if (find1(a[i].x) == find1(a[i].y))
    58. fk = 0;
    59. }
    60. }
    61. if (fk == 0)cout << "NO" << endl;
    62. else cout << "YES" << endl;
    63. }
    64. }

  • 相关阅读:
    【Qt】桌面应用开发 | 绘图事件和绘图设备 |文件操作
    智能感测型静电消除器通常具备哪些特点
    SpringBoot通过@Cacheable注解实现缓存功能
    【图像去噪】基于matlab双立方插值和稀疏表示图像去噪【含Matlab源码 2009期】
    大龄程序员的出路究竟在何处?从369个过来人问答贴里,我们得到了答案
    Springboot 开发 Web Flux
    如何实现table表头固定但是tbody可以滚动【附源码实例】
    js滚动条触底加载更多#js懒加载数据#步骤条布局懒加载
    csv文件和excel文件
    csapp attack lab phase3
  • 原文地址:https://blog.csdn.net/louisdlee/article/details/134444623