zoukankan      html  css  js  c++  java
  • nyoj 1022 合纵连横 (并查集<节点删除>)

    合纵连横

    时间限制:1000 ms  |  内存限制:65535 KB
    难度:3
     
    描述

    乱世天下,诸侯割据。每个诸侯王都有一片自己的领土。但是不是所有的诸侯王都是安分守己的,实力强大的诸侯国会设法吞并那些实力弱的,让自己的领土面积不断扩大。而实力弱的诸侯王为了不让自己的领土被吞并,他会联合一些其他同样弱小的诸侯国,组成联盟(联盟不止一个),来共同抵抗那些强大的诸侯国。 强大的诸侯国为了瓦解这些联盟,派出了最优秀的间谍来离间他们,使一些诸侯国退出联盟。最开始,每个诸侯国是一个联盟。

    有两种操作

    1、U x y 表示x和y在同一个联盟。(0≤x,y<n)

    2、D x   表示x退出联盟。

     
    输入
    多组测试数据
    第一行两个数,n和m(1 ≤ n≤ 10^5, 1 ≤ m ≤10^5),分别表示诸侯国的个数和操作次数。
    接下来有m行操作
    输出
    输出联盟的个数
    样例输入
    5 7
    U 0 1
    U 1 2
    U 0 3
    D 0
    U 1 4
    D 2
    U 0 2
    10 1
    U 0 9
    样例输出
    Case #1: 2
    Case #2: 9
     1 /**
     2     分析:主要考察并查集中点的删除
     3     算法:
     4         Ⅰ、以前并查集是以其 1 - n 中的元素即作根节点又作子节点
    5 《这样删除 pre [a] = n ++; 的话会使原先在一个区域的点可能不在一个区域了》 6 Ⅱ、现在我们将所有 1 - n 中的点作为子节点,n - 2n 的点作为根节点 7 《这样我们删除 pre [a] = 2n ++;的时候就不会打乱以前已在一个区域的点》 8 Ⅲ、其中 my_find()、my_join() 与以前并查集模板一致 9 10 关键代码: 11 void init () { 12 for (int i = 0; i < n; ++ i) 13 pre [i] = i + n; 14 for (int i = n; i < 2*n + m; ++ i) 15 pre [i] = i; 16 pos = 2*n; 17 return ; 18 ] 19 **/

    C/C++代码实现(AC):

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 int n, m, pre [301005], pos;
     6 
     7 void init () {
     8     for (int i = 0; i < n; ++ i)
     9         pre [i] = i + n;
    10     for (int i = n; i < n + n + m; ++ i)
    11         pre [i] = i;
    12     pos = n + n;
    13     return ;
    14 }
    15 
    16 int my_find (int x) {
    17     int n1 = x;
    18     while (n1 != pre [n1]) {
    19         n1 = pre [n1];
    20     }
    21     int i = x, j;
    22     while (pre [i] != n1) {
    23         j = pre [i];
    24         pre [i] = n1;
    25         i = j;
    26     }
    27     return n1;
    28 }
    29 
    30 void my_join (int a, int b) {
    31     int n1 = my_find (a), n2 = my_find (b);
    32     if (n1 != n2)
    33         pre [n1] = n2;
    34 }
    35 
    36 int main () {
    37     int k = 1;
    38     while (~scanf ("%d%d", &n, &m)) {
    39         init ();
    40         char c;
    41         int a, b, ans = 0, temp [301005] = {0};
    42         for (int i = 0; i < m; ++ i) {
    43             getchar ();
    44             scanf ("%c", &c);
    45             if (c == 'U') {
    46                 scanf ("%d%d", &a, &b);
    47                 my_join (a, b); 
    48             }
    49             else {
    50                 scanf ("%d", &a);
    51                 pre [a] = pos ++;
    52             }
    53         } 
    54         
    55         for (int i = 0; i < n; ++ i) { // 查找有多少个区域 
    56             if (!temp [my_find (i)]) { // 在一个区域的有共同的根节点 
    57                 temp [my_find (i)] = 1;
    58                 ++ ans;
    59             }
    60         }       
    61         printf ("Case #%d: %d
    ", k ++, ans);
    62     }
    63 } 
  • 相关阅读:
    Elasticsearch Network Settings
    Spring Application Event Example
    hibernate persist update 方法没有正常工作(不保存数据,不更新数据)
    快速自检电脑是否被黑客入侵过(Linux版)
    快速自检电脑是否被黑客入侵过(Windows版)
    WEB中的敏感文件泄漏
    Nginx日志分析
    关系型数据库设计小结
    软件开发的一些"心法"
    关于DNS,你应该知道这些
  • 原文地址:https://www.cnblogs.com/GetcharZp/p/8982705.html
Copyright © 2011-2022 走看看