HDU 2473 Junk-Mail Filter 并查集,虚拟删除操作

给定两种操作

第一种是合并X Y

第二种是把X分离出来,就是从原来的集合中分离出来,其它的关系不变。

关键是怎么分离,可以考虑把它变成一个其它值。HASH[i] = other_val

然后用新值去做并查集即可、

需要注意的一点就是

加入现在根是1,fa[1] = 1, fa[2] = 1, fa[3] = 1

那么如果你删除了1,这应该输出2.但是现在是fa[2] = 1,是一个不存在的根了,这个时候ans应该+1,但是按照并查集的思路

if (find(HASH[i]) == HASH[i]) ans++ 是不行的,因为这个根已经不存在了。

解决方法就是标记是否为虚根,del[i] = true表示删除了,但是枚举fa[3]的时候就要避免重新加,需要取消标记。

如果这时再有M 4 2,那么就把fa[4] = 1,用虚根表示即可。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 2e6 + 20;
int fa[maxn];
int HASH[maxn];
bool del[maxn];
void init() {
    memset(del, 0, sizeof del);
    for (int i = 0; i < maxn; ++i) fa[i] = i;
    for (int i = 0; i < maxn; ++i) HASH[i] = i;
}
int find(int u) {
    if (fa[u] == u) return u;
    else return fa[u] = find(fa[u]);
}
void merge(int x, int y) {
    x = find(x);
    y = find(y);
    if (x != y) {
        fa[y] = x;
    }
}
int n, m;
int ff;
void work() {
    init();
    int t = n;
    for (int i = 1; i <= m; ++i) {
        char str[11];
        int a, b;
        scanf("%s", str);
        if (str[0] == ‘M‘) {
            scanf("%d%d", &a, &b);
            merge(HASH[a], HASH[b]);
        } else {
            scanf("%d", &a);
            del[HASH[a]] = 1;
            HASH[a] = n++;
        }
    }
    int ans = 0;
    for (int i = 0; i < t; ++i) {
        if (find(HASH[i]) == HASH[i]) ans++;
        if (del[find(HASH[i])]) {
            del[find(HASH[i])] = 0;
            ans++;
        }
    }
//    cout << find(2) << endl;
    printf("Case #%d: %d\n", ++ff, ans);
    return;
}

int main() {
#ifdef local
    freopen("data.txt","r",stdin);
#endif
    while (scanf("%d%d", &n, &m) != EOF && (n + m)) {
        work();
    }
    return 0;
}

时间: 2024-10-21 17:24:34

HDU 2473 Junk-Mail Filter 并查集,虚拟删除操作的相关文章

HDU 2473 Junk-Mail Filter (并查集的删除操作)

Problem Description Recognizing junk mails is a tough task. The method used here consists of two steps: 1) Extract the common characteristics from the incoming email. 2) Use a filter matching the set of common characteristics extracted to determine w

[HDOJ2473]Junk-Mail Filter(并查集,删除操作,马甲)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2473 给两个操作:M X Y:将X和Y看成一类. S X:将X单独划归成一类. 最后问的是有多少类. 并查集,但是带有删除操作.然而并查集本身不支持删除,网上说可以引入一个id来表示一个点.就好像一个人上网有很多小号一样,假如这个人的小号被封掉并且永久不能解封,还想继续玩下去的话那就重新建一个号,再生成一个id,表示这个id是这个人就好了. 注意在删除操作的时候不能把原来id的pre值重置. 1 /

并查集的删除操作

C - Junk-Mail Filter  HDU - 2473 题目大意:就是一堆信件,然后有两个操作,一个是把一堆信件归在一个文件夹,一个就是把一个信件从文件夹中取出,最后问有多少个文件夹,一开始所有信件都是单独的文件夹. 其实就是一个简单的并查集删除的操作,当删除时就创建新的结点来代替它,要注意的是数组的范围,虽然信件只有10的5次方,但是操作有10的6次方,因为删除时还得创建新节点,所以数组一定要开大,不然不是WR就是TL.最后的输出可以直接用set,也可以用数组标记信件是归在哪个文件夹

朋友(并查集的删除操作 可看作是插入操作的逆序)

小 z 被选为他们村的村长, 现在小 z 调查他们村上的关系. 如果村民 a 和村民 b 是朋友, 村民 b 和村民 c 是朋友, 那么村民 a 和村民 c 也是朋友. 那么村上的村民就会形成一个"朋友" 团队, 现在小 z 想知道他们村长有多少个这样的团队. 同时, 他们村会有人离开村子到城里谋求发展, 那么小 z 也想知道, 当他们离开后村上的"朋友" 团队.★数据输入输入第一行包括两个整数, N, M. N 表示一共有 N 个人, M 表示一个共有M 对关系.

HDU 3635 延缓更新的并查集

Dragon Balls Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2839    Accepted Submission(s): 1097 Problem Description Five hundred years later, the number of dragon balls will increase unexpecte

HDU 3461 Code Lock(并查集的应用+快速幂)

* 65536kb,只能开到1.76*10^7大小的数组.而题目的N取到了10^7,我开始做的时候没注意,用了按秩合并,uset+rank达到了2*10^7所以MLE,所以貌似不能用按秩合并. 其实路径压缩也可以不用.............  题目的大意: 一个密码锁上有编号为1到N的N个字母,每个字母可以取26个小写英文字母中的一个.再给你M个区间[L,M],表示该区间的字母可以一起同步"增加"(从'a'变为'b'为增1,'z'增1为'a').假如一组密码按照给定的区间进行有限

HDU 1558 Segment set (并查集+线段非规范相交)

题目链接 题意 : 如果两个线段相交就属于同一集合,查询某条线段所属集合有多少线段,输出. 思路 : 先判断与其他线段是否相交,然后合并. 1 //1558 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <cmath> 6 #define eps 1e-8 7 #define zero(x) (((x) > 0 ? (x) : (-x)) < e

关于一般的并查集求根操作的一组对照研究

说道并查集,大家一定对于以多叉树状结构为基础的并查集并不陌生最常见的两种写法如下 1 private function getfat(x:longint):longint; 2 begin 3 while x<>c[x] do x:=c[x]; 4 exit(x); 5 end; 1 private function getfat(x:longint):longint; 2 begin 3 if x<>c[x] then exit(getfat(c[x])) else exit(x

hdu 2473 Junk-Mail Filter 并查集删除

点击打开链接 http://acm.hdu.edu.cn/showproblem.php?pid=2473 题意:给出n种操作,M a b表示a和b是同一个并查集,S a表示在并查集中删除a,要注意的是,如果1和2是一个并查集,2和3是一个并查集,那么1和3也是一个并查集,即使删除2之后,我们依然可以得到1和3还是一个集合里的. 思路:由于并查集是一种树结构,无法在树种删除一个点后还让树继续保持着之前的样子,所以我们删除是采取的操作是使用映射,一开始所有点的映射都是自己,然后删除操作就是把这个点

HDU 2473 Junk-Mail Filter (并查集节点删除)

Junk-Mail Filter Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 7254    Accepted Submission(s): 2307 Problem Description Recognizing junk mails is a tough task. The method used here consists o