并查集的删除操作

C - Junk-Mail Filter  HDU - 2473

题目大意:就是一堆信件,然后有两个操作,一个是把一堆信件归在一个文件夹,一个就是把一个信件从文件夹中取出,最后问有多少个文件夹,一开始所有信件都是单独的文件夹。

其实就是一个简单的并查集删除的操作,当删除时就创建新的结点来代替它,要注意的是数组的范围,虽然信件只有10的5次方,但是操作有10的6次方,因为删除时还得创建新节点,所以数组一定要开大,不然不是WR就是TL。最后的输出可以直接用set,也可以用数组标记信件是归在哪个文件夹,注意的是后面创建的结点是虚拟的,真实的信件有对它们的映射,所以最后统计时只考虑真实信件。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<set>
 4 using namespace std;
 5 struct Email{
 6     int id,gen;
 7 }em[1201108];//要够大
 8 int n,m;
 9 int gui(int x);
10 void bing(int x,int y);
11 void del(int x);
12 int main()
13 {
14     int i,x,y,test=0;
15     char c;
16     while(scanf("%d%d",&n,&m)!=EOF&&(n||m))
17     {
18         int N=n;
19         set<int> s;
20         for(i=0;i<n;i++)
21         {
22             em[i].id=i;
23             em[i].gen=i;
24         }//初始自己映射自己,自己是自己的根节点。。。。
25         while(m--)
26         {
27             cin>>c;
28             if(c==‘M‘)
29             {
30                 scanf("%d%d",&x,&y);
31                 bing(em[x].id,em[y].id);
32             }
33             else
34             {
35                 scanf("%d",&x);
36                 del(x);
37             }
38         }
39         for(i=0;i<N;i++)//只考虑真实信件
40             s.insert(gui(em[i].id));//每个集合的根节点只记录一次
41         printf("Case #%d: %d\n",++test,s.size());
42     }
43     return 0;
44 }
45 int gui(int x)
46 {
47     if(em[x].gen==x)
48         return x;
49     return em[x].gen=gui(em[x].gen);
50 }
51 void bing(int x,int y)//对节点所映射的节点进行并操作
52 {
53     int bx=gui(x);
54     int by=gui(y);
55     if(bx!=by)
56         em[by].gen=bx;
57     return ;
58 }
59 void del(int x)//创造虚拟节点来代替原来节点
60 {
61     em[x].id=n;//节点映射到新创建的虚拟节点
62     em[n].gen=n;
63     n++;
64     return ;
65 }

原文地址:https://www.cnblogs.com/LMCC1108/p/9355182.html

时间: 2024-08-02 16:35:47

并查集的删除操作的相关文章

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 /

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

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

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

说道并查集,大家一定对于以多叉树状结构为基础的并查集并不陌生最常见的两种写法如下 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

Restructuring Company和Almost Union-Find 并查集的区间合并与并查集的删除

Restructuring Company Even the most successful company can go through a crisis period when you have to make a hard decision - to restructure, discard and merge departments, fire employees and do other unpleasant stuff. Let's consider the following mo

UVA11987 - Almost Union-Find (并查集带删除)

题目链接 题目大意:给出三个操作: 1 p q 表示将p q 这两个数所在的集合合并在一起.2 p q表示将p这个数从原有的集合中拿出来放到q所在的集合中.3 p表示查询p所在的集合总共有几个元素,和是多少. 解题思路:并查集.只是并查集中并没有删除的操作.所以就需要将删除的这个点的影响降到0,也就是给删除的点申请一个新的id,以后都是用这个新的id来表示这个点,这样原来的那个集合里的点p就没意义,自然影响就为0. 代码: #include <cstdio> #include <cstr

Almost Union-Find 并查集的删除

Almost Union-Find I hope you know the beautiful Union-Find structure. In this problem, you're to implement something similar, but not identical. The data structure you need to write is also a collection of disjoint sets, supporting 3 operations: 1 p

zoj 3261 Connections in Galaxy War(并查集+离线逆向操作)

 题目:给出一些点,每个点有权值,然后有一些边,相连.无向的.然后有一些操作 query a.表示从a出发的能到达的所有点权值最大的点的编号(相同取编号最小,而且权值要比自己大) destory a,b 表示删除连接a,b的边 思路并查集,但是要逆向处理,所以先离线读入,从后向前处理,于是对于destroy操作,等价于连接两个点的操作,然后对于每个询问输出即可 #include<cstdio> #include<cstring> #include<cmath> #i

并查集的一般操作 ①

Rt 题目背景 A地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车.政府派人修复这些公路. 题目描述 给出A地区的村庄数N,和公路数M,公路是双向的.并告诉你每条公路的连着哪两个村庄,并告诉你什么时候能修完这条公路.问最早什么时候任意两个村庄能够通车,即最早什么时候任意两条村庄都存在至少一条修复完成的道路(可以由多条公路连成一条道路) 输入输出格式 输入格式: 第1行两个正整数N,M 下面M行,每行3个正整数x, y, t,告诉你这条公路连着x,y两个村庄,在时间t时能修复完成这条公路.