HLJU 1105 cpc 喵喵的拆分集合 (并查集的逆向操作)

1105: 喵喵的拆分集合

Time Limit: 1 Sec  Memory Limit: 128 MB

Submit: 37  Solved: 8

[Submit][Status][Web
Board
]

Description

众所周知,DoubleQ是DS(Data Structure)粉,她最爱DS了。现在她要实现一个神奇的DS,支持下列两个操作:

-删除某条边,表示为”D x”,即为删除第x条边

-查询两点是否属于一个集合,表示为”Q a b”,即为查询节点a与节点b是否在一个集合内,若在同一个集合内,输出”Yes”,否则输出”No”(输出不包括引号)

n<=100000,m<=100000,q<=100000

Input

多组数据。

对于每组数据,第一行包括三个正整数,分别代表数据结构中节点的个数n,边数m,操作数q

接下来的m行代表第i条边(从1开始),第i条边连接u和v两个顶点(无重边,无自环)

再接下来的q行每行包括一个格式如题描述操作

Output

对于每一个查询,输出包括一行,表示查询结果,即如果两点属于同一个集合输出”Yes”,否则输出”No”。

Sample Input

5 4 6
1 2
2 3
4 5
1 3
Q 1 2
D 1
Q 1 2
Q 3 4
D 2
Q 1 2

Sample Output

Yes
Yes
No
No

解析:逆向处理。由于删边不好实现,我们可以换个思路。先把所有操作保留下来,然后再倒序执行各操作,这样的话,删边就相当于先不把这条边加进去,然后再按照倒序执行各个操作即可。

AC代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 100000 + 10;

typedef struct node{
    int a, b;
}edge;
edge e[maxn], q[maxn];
int del[maxn], is_d[maxn];
bool s[maxn];
int par[maxn];                 //father[]数组
char op[maxn][4];              //保存操作

inline int getpar(int x){
    return x == par[x] ? x : par[x] = getpar(par[x]);
}

inline void unin(int x, int y){
    int a = getpar(x), b = getpar(y);
    if(a != b)  par[a] = b;
}

int main(){
    #ifdef sxk
        freopen("in.txt", "r", stdin);
    #endif // sxk

    std::ios::sync_with_stdio(false);
    std::cin.tie(0);

    int n, m, k;
    while(scanf("%d%d%d", &n, &m, &k)!=EOF){
        memset(is_d, 0, sizeof(is_d));
        memset(s, false, sizeof(s));
        memset(e, 0, sizeof(e));
        memset(q, 0, sizeof(q));
        memset(del, 0, sizeof(del));
        for(int i=1; i<=n; i++){
            par[i] = i;
        }
        for(int i=1; i<=m; i++){
            scanf("%d%d", &e[i].a, &e[i].b);
        }

        int fo = 0, foo = 0;
        for(int i=1; i<=k; i++){
            scanf("%s", &op[i]);
            if(op[i][0] == 'Q'){
                foo ++;
                scanf("%d%d", &q[foo].a, &q[foo].b);
            }
            else {
                fo ++;
                scanf("%d", &del[fo]);
                is_d[ del[fo] ] = 1;
            }
        }
        for(int i=1; i<=m; i++){
            if(!is_d[i]) unin(e[i].a, e[i].b);
        }
        int cnt = foo;
        for(int i=k; i>0; i--){
            if(op[i][0] == 'Q'){
                if(getpar( q[cnt].a ) == getpar( q[cnt].b ))
                    s[cnt] = true;
                else s[cnt] = false;
                cnt --;
            }
            else{
                unin(e[ del[fo] ].a, e[ del[fo] ].b);
                fo --;
            }
        }
        for(int i=1; i<=foo; i++) printf("%s\n", s[i] == true ? "Yes" : "No");
    }
    return 0;
}
时间: 2024-10-17 09:44:11

HLJU 1105 cpc 喵喵的拆分集合 (并查集的逆向操作)的相关文章

数据结构(四)树---集合的表示及查找(并查集)

一:集合运算 交,并,补,差,判断一个元素是否属于某一集合 并查集将在判断连通性和是否成环上面起到至关重要的作用 二:并查集 (一)集合并 并集间有一元素相连 (二)查某元素属于什么集合 可用树来表示集合,每个结点代表一个集合元素 S1={1,2,4,7} S2={3,5,8} S3={6,9,10} 我们可以使用双亲表示法来判断某个结点的根结点,从而判断是否是使用某个集合 #define MAX_TREE_SIZE 100 typedef int TElemType; typedef stru

喵喵的IDE

喵喵的IDE Time Limit: 20000/10000MS (Java/Others)Memory Limit: 512000/256000KB (Java/Others) SubmitStatisticNext Problem Problem Description 喵喵有一个神奇的IDE,这个IDE自带一个cache,还有一个当前编辑区editarea,初始的时候这个 cache 中有一个字符串 cachebegin. 喵喵想打按照顺序打N个字符串 x,她可以进行三种操作. 打之前 e

CPC23-4-K. 喵喵的神数 (数论 Lucas定理)

喵喵的神?数 Time Limit: 1 Sec Memory Limit: 128 MB Description 喵喵对组合数比較感兴趣,而且对计算组合数很在行. 同一时候为了追求有后宫的素养的生活,喵喵每天都要研究 质数. 我们先来复习一下什么叫做组合数.对于正整数P.T 然后我们再来复习一下什么叫质数.质数就是素数,假设说正整数N的约数仅仅有1和它本身,N就是质数:另外. 1不是质数. 今天,喵喵想要知道 Input 输入第一行是一个整数N(N<=1000). 接下来N行,每行包含一个正整

BZOJ 2754([SCOI2012]喵喵叫的星球-统计序列的后缀阵列中子序列出现次数)

2754: [SCOI2012]喵喵叫的星球 Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 805  Solved: 380 [id=2754" style="color:blue; text-decoration:none">Submit][Status][Discuss] Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 如果课堂上有N个喵星人,每一

喵哈哈村的代码传说 第四章 并查集

描述 有一个非常大的村子,叫做喵哈哈村,一开始他们都互相不认识,但是渐渐地,他们就会相互来往,所以就会有以下问题的产生: 1 x y,x家与y家成为朋友 2 x y,提问x家和y家是否为朋友,间接成为朋友也算. 输入 本题包含若干组测试数据.第一行两个整数n,m,表示这个村子有n户家庭,一开始他们都不认识.含有m个问题.接下来m行:1 x y2 x y分别表示操作和询问.满足1<=n,m<=100000,注意x 输出 是朋友输出Yes,否则输出N 样例输入1 复制 3 4 2 1 2 2 1

BC68(HD5606) 并查集+求集合元素

tree Accepts: 143 Submissions: 807 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) 问题描述 有一个树(nn个点, n-1n−1条边的联通图),点标号从11~nn,树的边权是00或11.求离每个点最近的点个数(包括自己). 输入描述 第一行一个数字TT,表示TT组数据. 对于每组数据,第一行是一个nn,表示点个数,接下来n-1n−1,每行三个整数u,

[算法系列之二十八]并查集(不相交集合)

一 概述 并查集(Disjoint set或者Union-find set)是一种树型的数据结构,常用于处理一些不相交集合(Disjoint Sets)的合并及查询问题. 有一个联合-查找算法(union-find algorithm)定义了两个操作用于此数据结构: Find:确定元素属于哪一个子集.它可以被用来确定两个元素是否属于同一子集. Union:将两个子集合并成同一个集合. 因为它支持这两种操作,一个不相交集也常被称为联合-查找数据结构(union-find data structur

并查集/生成树问题 | 问题集合

写在前面 似乎没什么可以写的? 那还是扯一下吧. 题目大部分带题号没给特殊地址/链接的都是洛谷的题 然后亲戚和朋友两道题库被我刷烂的题我就不搬进来了(:懒 P1536 村村通 题目描述 某市调查城镇交通状况,得到现有城镇道路统计表.表中列出了每条道路直接连通的城镇.市政府"村村通工程"的目标是使全市任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要相互之间可达即可).请你计算出最少还需要建设多少条道路? 输入格式: 每个输入文件包含若干组测试测试数据,每组测试数据的第一行给出

集合问题 离线+并查集 HDU 3938

题目大意:给你n个点,m条边,q个询问,每条边有一个val,每次询问也询问一个val,定义:这样条件的两个点(u,v),使得u->v的的价值就是所有的通路中的的最长的边最短.问满足这样的点对有几个. 思路:我们先将询问和边全部都按照val排序,然后我们知道,并查集是可以用来划分集合的,所以我们就用并查集来维护每一个集合就行了. //看看会不会爆int!数组会不会少了一维! //取物问题一定要小心先手胜利的条件 #include <bits/stdc++.h> using namespac