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\n", k ++, ans);
62     }
63 } 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
孪生素数是指两个素数之间的差值为2的素数对。通过筛选法可以找出给定素数范围内的所有孪生素数的组数。 在引用的代码中,使用了递归筛选法来解决孪生素数问题。该程序首先使用循环将素数的倍数标记为非素数,然后再遍历素数数组,找出相邻素数之间差值为2的素数对,并统计总数。 具体实现过程如下: 1. 定义一个数组a[N,用来标记数字是否为素数,其中N为素数范围的上限。 2. 初始化数组a,将0和1标记为非素数。 3. 输入要查询的孪生素数的个数n。 4. 循环n次,每次读入一个要查询的素数范围num。 5. 使用两层循环,外层循环从2遍历到num/2,内层循环从i的平方开始,将素数的倍数标记为非素数。 6. 再次循环遍历素数数组,找出相邻素数之间差值为2的素数对,并统计总数。 7. 输出总数。 至此,我们可以使用这个筛选法的程序来解决孪生素数问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [python用递归筛选法求N以内的孪生质数(孪生素数)](https://blog.csdn.net/weixin_39734646/article/details/110990629)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [NYOJ-26 孪生素数问题](https://blog.csdn.net/memoryofyck/article/details/52059096)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值