并查集+思维——X-Plosives

一、问题描述(题目链接

有n种化合物,每种化合物由两种元素组成。当几种的化合物数量等于他们所含不同元素的数量时,就会发生爆炸。现在依次给出化合物的组成,当新的化合物与之前的化合物放在一起会发生爆炸时,就不能允许这个化合物放进来。输出拒绝的次数。

二、问题分析

把元素看成点,化合物看成边,每次新的化合物进来当成连一条边。

如果图中没有环,则每个连通分量是一棵树,其边数等于点数减1,不可能存在爆炸的情况;如果图中有环,则这个环上点数等于边数,就会爆炸。

使用并查集连边,如果要连的两个点在同一集合中,则答案加1。

三、代码实现

 1 #include<stdio.h>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6
 7 typedef long long LL;
 8 const int maxn = 100000 + 10;
 9 int par[maxn];
10 int n, ans;
11
12 void init()
13 {
14     for (int i = 0; i < maxn; i++)
15         par[i] = i;
16 }
17
18 int find_set(int x)
19 {
20     if (x != par[x])
21         par[x] = find_set(par[x]);
22     return par[x];
23 }
24
25 void unite(int x, int y)
26 {
27     int rootx = find_set(x);
28     int rooty = find_set(y);
29
30     if (rootx == rooty)            //如果两个元素在同一集合,则会爆炸;此时应拒绝加入,答案加一
31     {
32         ans++;
33         return;
34     }
35
36     par[rootx] = rooty;
37 }
38
39 int main()
40 {
41     int x,y;
42     while (scanf("%d",&x) == 1)
43     {
44         ans = 0;
45         init();
46         while (x != -1)
47         {
48             scanf("%d", &y);
49             unite(x, y);
50             scanf("%d", &x);
51         }
52         printf("%d\n", ans);
53     }
54     return 0;
55 }

原文地址:https://www.cnblogs.com/lfri/p/9484600.html

时间: 2024-12-16 11:10:06

并查集+思维——X-Plosives的相关文章

并查集+思维——The Door Problem

一.问题描述(题目链接) 有n个门和m个开关,每个开关可以控制任意多的门,每个门严格的只有两个开关控制,问能否通过操作某些开关使得所有门都打开.(给出门的初始状态). 二.问题分析 大部分开关问题首先要想到的一点就是任何开关操作两次以上都是无意义的,因此对于每个开关,我们要么操作一次,要么不操作. 因为已知门的初始状态,每个门由两个开关控制,所以我们可以调节这两个开关,使门保持打开的状态. 我们考虑用并查集维护开关之间的关系,因为每个开关有操作和不操作两种状态.,因此,我们要把每个点拆成两个点,

Codeforces 200A Cinema 并查集 + 思维 (看题解)

Cinema 感觉这个题好神啊... 首先如果 n 比 m 大, 我们先旋转90度. 我们要加入一个(x, y)的时候, 我们枚举答案所在的行离 x 的距离 g , 然后对于x + g 行来说 我们找到(x + g, y)左边的第一个和右边的第一个未被占的位置,更新答案, 如果 g > 答案 退出. 左边和右边第一个未被占的可以用并查集维护, 把连续占了的并成一个联通块, 维护最小值和最大值. 对于 2000 * 2000的图来说, 对于每一次, 最多sqrt( n )就能找到答案, 因为最坏情

CodeForces - 763A(并查集/思维)

题意 https://vjudge.net/problem/CodeForces-763A 一棵无根树中各个节点被染上了一种颜色c[i] 现在让你选择一个点作为根节点,使得这个根节点的所有儿子满足以该儿子节点的作为根的子树中所有点颜色均相同(不同儿子为根的子树颜色可以不同) 思路 俺的方法: 暴力水过.用并查集把相同颜色的连了边的点缩点,然后枚举每个点作为答案,判断这个点所连的的所有点的所在相同颜色连通块的大小之和是否等于n-1即可(除去自己这个点). 正解: 先计算每个点与所连的点的颜色不同的

并查集+思维——Destroying Array

一.题目描述(题目链接) 给定一个序列,按指定的顺序逐一删掉,求连续子序列和的最大值.例如序列1 3 2 5,按3 4 1 2的顺序删除,即依次删除第3个.第4个.第1个.第2个,答案为5 4 3 0. 二.问题分析 我们知道从并查集中删除元素很难,而合并非常简单.所以我们可以反过来思考,正向删除元素等同于反向添加元素,将结果存起来反向输出即可.每次添加一个元素,更新最大值.很明显新加入的点只影响相邻元素的值.每添加一个元素有4种情况:单独成集合,只与前面的成集合,只与后面的成集合,既与前面的成

Codeforces 722C(并查集 + 思维)

题目链接:http://codeforces.com/problemset/problem/722/C 思路: 题目给的操作数从第 1 个到第 N 个数是删除原数组中的一个数, 那么反过来从后往前就是增加原数组中的一个数, 每增加一个值, 那么就有四种情况: 第一种和前后都不连续, 即自成一个集合; 第二种:和前面的数连续, 即和前一个数在一个集合; 第三种和之后一个数连续, 即和之后的一个数在一个集合; 第四种既和前面一个数连续也和后面一个数连续,那么说明前后两个集合被这个数合并成一个集合.

HDU 4496 D-City(并查集,逆思维)

题目 熟能生巧...常做这类题,就不会忘记他的思路了... //可以反过来用并查集,还是逐个加边,但是反过来输出...我是白痴.....又没想到 //G++能过,C++却wa,这个也好奇怪呀... #include<stdio.h> #include<string.h> int fx,fy,r,bin[10010]; int x[100010],y[100010],n,m,i,count,ans[100010],j; int find(int x) { //改成这样就不会超时了么好

Codeforces Round #423 (Div. 2) C 思维,并查集 或 线段树 D 树构造,水

Codeforces Round #423 (Div. 2, rated, based on VK Cup Finals) C. String Reconstruction   思维,并查集 或 线段树 题意:一个字符串被删除了,但给出 n条信息,要还原出可能的字典序最小的字符串.信息有:字符串ti,ki个位置xi,表明原本的字符串在xi位置是以字符串ti开头的. tags:惨遭 fst,一开始把所有字符串都存下来,排序做的,结果爆内存了.. 方法1: 考虑并查集,对于字符串 ti,在位置xi,

hdu6074[并查集+LCA+思维] 2017多校4

看了标答感觉思路清晰了许多,用并查集来维护全联通块的点数和边权和. 用另一个up[]数组(也是并查集)来保证每条边不会被重复附权值,这样我们只要将询问按权值从小到大排序,一定能的到最小的边权和与联通块中的点数. 下面是过程分析.过程中一共运用了两个并查集. [数据]110 31 21 32 42 53 63 74 85 95 109 6 3 1 501 4 2 5 209 10 8 10 40[分析]首先我们将图构建出来我们将m次询问按权值从小到大排序后: 1 4 2 5 209 10 8 10

Codeforces 1263D. Secret Passwords(并查集,思维)

传送门 题意: 给n个字符串,如果任意两个字符串有一个字符相同,则他们相同即属于同一集合,问总共有几个集合 思路: 并查集,对于每个字符串,把每个字符与第一个字符合并,因为他们肯定在同一个集合(意思是每个字符串都当成ch[0],看有几个不同的),合并之后,for(1-26)以它为根的个数,即集合的个数,貌似是思维题(并查集裸题) 代码: #include <iostream> #include <stdio.h> #include <algorithm> #includ