Junk-Mail Filter

Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 8687 Accepted Submission(s): 2753

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 whether the email is a spam.

We want to extract the set of common characteristics from the N sample junk emails available at the moment, and thus having a handy data-analyzing tool would be helpful. The tool should support the following kinds of operations:

a) “M X Y”, meaning that we think that the characteristics of spam X and Y are the same. Note that the relationship defined here is transitive, so
relationships (other than the one between X and Y) need to be created if they are not present at the moment.

b) “S X”, meaning that we think spam X had been misidentified. Your tool should remove all relationships that spam X has when this command is received; after that, spam X will become an isolated node in the relationship graph.

Initially no relationships exist between any pair of the junk emails, so the number of distinct characteristics at that time is N.
Please help us keep track of any necessary information to solve our problem.

Input
There are multiple test cases in the input file.
Each test case starts with two integers, N and M (1 ≤ N ≤ 10 5, 1 ≤ M ≤ 106), the number of email samples and the number of operations. M lines follow, each line is one of the two formats described above.
Two successive test cases are separated by a blank line. A case with N = 0 and M = 0 indicates the end of the input file, and should not be processed by your program.

Output
For each test case, please print a single integer, the number of distinct common characteristics, to the console. Follow the format as indicated in the sample below.

Sample Input
5 6
M 0 1
M 1 2
M 1 3
S 1
M 1 2
S 3

3 1
M 1 2

0 0

Sample Output
Case #1: 3
Case #2: 2

并查集删点的操作看看了很久,找了无数篇博客,但是感觉除了一个有画图的博客之外其他的讲的都不是很详细,因此在有一点理解之后想写一下自己的看法
首先题目中分M(合并)和S(分离)两种操作,显然前者非常简单,后者有一点难理解。由于我一开始连第一个样例都看不懂,先解释一下题目第一组数据样例吧。

操作 集合关系
M 0 1 {0 1} {2} {3} {4}
M 1 2 {0 1 2} {3} {4}
M 1 3 {0 1 2 3} {4}
S 1 {0 2 3} {1} {4}
M 1 2 {0 1 2 3} {4}
S 3 {0 1 2} {3} {4}

题目中说Your tool should remove all relationships that spam X has when this command is received,可能会误认为是把它所连的边全部抹掉,其实题目中集合的概念可以看成一些泡泡,M就是融合,S就是分裂,显然分裂出去一定是出去一个,但是融合就不一定了,比如{0 2 3}和{4 5 6},两边集合中任意地取出两个数进行融合就会使得两个集合融合在一起形成{0 2 3 4 5 6},就是说虽然M A B连接的是一个,但是实际上会把A所在的集合和B所在的集合联合到一起。然后这样就可以解释第一组样例了。1出去之后2又把1拉回来,然后把3分裂了出去。因此结果为3组如上表所示。
然后重点就是如何进行这样的S操作,其他很多人的博客已经解释过仅仅把祖先改掉是没用的,因此需要另一种思路:最普通的并查集是把数组元素进行合并,而数组元素是不会变的,永远都是最大编号的范围内——只认人。
而删点操作要换一换,不是把人合并,而是把这个位置的人合并——认位置不认人。放到题目里就是把分裂出去的人本身替换掉,若再拉回来就是另一个实体,但是回去之后的位置却是分裂之前的那个人所在的位置。比如下列这组数据
6 7
M 0 1
M 1 2
M 2 3
S 3
M 3 4
M 4 5
M 0 3

最后3的位置会被6替换掉(题目中N=6指的是编号范围从0~N-1)
然后后面的派3去融合其实是派6去融合。但是算的还是3的位置。

代码:

#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<string>
#include<deque>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f
#define MM(x) memset(x,0,sizeof(x))
#define MMINF(x) memset(x,INF,sizeof(x))
typedef long long LL;
const double PI = acos(-1.0);
const int N = 1100010;
int pre[N], ran[N]; //pre记录父亲是谁,ran集合元素个数
int vir[N], mark[N]; //vir记录某个位置的孩子是谁,mark统计集合个数用的数组mark
void init()
{
for (int i = 0; i < N; i++)
{
pre[i] = i;
ran[i] = 1;
vir[i] = i;
}
MM(mark);
}
int find(int n)
{
if (n != pre[n])
return pre[n] = find(pre[n]);
return pre[n];
}
void joint(int a, int b)
{
int fa = find(a), fb = find(b);
if (fa != fb)
{
if (ran[fa] >= ran[fb])
{
ran[fa] += ran[fb];
pre[fb] = fa;
ran[fb] = 0;
}
else
{
ran[fb] += ran[fa];
pre[fa] = fb;
ran[fa] = 0;
}
}
}
int main(void)
{
int n, m, i, j, a, b, c, k, cas = 0;
char ops[5];
while (~scanf("%d%d", &n, &m) && (n || m))
{
init();
k = n;
for (i = 0; i < m; i++)
{
scanf("%s", ops);
if (ops[0] == 'M')
{
scanf("%d%d", &a, &b);
joint(vir[a], vir[b]); //合并这个两个位置的人
}
else
{
scanf("%d", &c);
ran[find(vir[c])]--;//分离出去一个原来的集合个数减一
vir[c] = k; //这个位置的人换成无关的人
pre[k] = k; //刚分离出去刚形成的新点,把祖先先改为自己
k++;//更新已用人员
}
}
int r = 0;
for (i = 0; i < n; i++)
{
int f = find(vir[i]);
if (!mark[f])
{
r++;
mark[f] = 1;
}
}
printf("Case #%d: %d\n", ++cas, r);
}
return 0;
}

HDU——2473Junk-Mail Filter(并查集删点)的更多相关文章

  1. HDU 2473 Junk-Mail Filter(并查集+删点,设立虚父节点/找个代理)

    题意:有N封邮件, 然后又两种操作,如果是M X Y , 表示X和Y是相同的邮件.如果是S X,那么表示对X的判断是错误的,X是不属于X当前所在的那个集合,要把X分离出来,让X变成单独的一个.最后问集 ...

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

    http://acm.hdu.edu.cn/showproblem.php?pid=2473 给定两种操作 第一种是合并X Y 第二种是把X分离出来,就是从原来的集合中分离出来,其它的关系不变. 关键 ...

  3. hdu 2473 Junk-Mail Filter (并查集之点的删除)

    Junk-Mail Filter Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  4. (step5.1.2)hdu 2473(Junk-Mail Filter——并查集)

    题目大意:输入两个整数n,m(n表示点的个数,m表示操作数).在接下来的m行中,对点的操作有两种 1)M a b . 表示将a.b并到一个集合中 2)S a .表示将a从原来的集合中去除,而成为一个单 ...

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

    题目地址:pid=2473">HDU 2473 这题曾经碰到过,没做出来. .如今又做了做,还是没做出来. ... 这题涉及到并查集的删除操作.想到了设一个虚节点,可是我把虚节点设为了 ...

  6. HDU 2473 Junk-Mail Filter 并查集删除(FZU 2155盟国)

    http://acm.hdu.edu.cn/showproblem.php?pid=2473 http://acm.fzu.edu.cn/problem.php?pid=2155 题目大意: 编号0~ ...

  7. ZOJ 3261 - Connections in Galaxy War ,并查集删边

    In order to strengthen the defense ability, many stars in galaxy allied together and built many bidi ...

  8. HDU 1811 拓扑排序 并查集

    有n个成绩,给出m个分数间的相对大小关系,问是否合法,矛盾,不完全,其中即矛盾即不完全输出矛盾的. 相对大小的关系可以看成是一个指向的条件,如此一来很容易想到拓扑模型进行拓扑排序,每次检查当前入度为0 ...

  9. hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点)

    hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点) 题意: 给一张无向连通图,有两种操作 1 u v 加一条边(u,v) 2 u v 计算u到v路径上桥的个数 ...

随机推荐

  1. codevs 3054 高精度练习-文件操作

    时间限制: 1 s  空间限制: 64000 KB  题目等级 : 钻石 Diamond 题目描述 Description 输入一组数据,将每个数据加1后输出 输入描述 Input Descripti ...

  2. 剑指offer——把字符串转换成整数(c++)

    题目描述请你写一个函数StrToInt,实现把字符串转换成整数这个功能.当然,不能使用atoi或者其他类似的库函数. 示例 1:输入: " -42"输出: -42解释: 第一个非空 ...

  3. javaEE(5)_Cookie和Session

    一.会话 1.什么是会话?会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话.类似打电话一样.2.会话过程中要解决的一些问题?每个用户 ...

  4. java在线聊天项目0.9版 实现把服务端接收到的信息返回给每一个客户端窗口中显示功能之客户端接收

    客户端要不断接收服务端发来的信息 与服务端不断接收客户端发来信息相同,使用线程的方法,在线程中循环接收 客户端修改后代码如下: package com.swift; import java.awt.B ...

  5. 字符串数组 输入3个字符串,要求按由小到大的字母顺序输出; 输入n个学生的姓名和学号到字符串数组中,在输入一个姓名,如果班级有该生则返回其信息,否则返回本班无此人

    输入3个字符串,要求按由小到大的字母顺序输出 如 输入franch england china,输出结果是china england franch 三个数排序输出,比较三个数的大小怎么做? a=18 ...

  6. 什么是二维数组?二维遍历?Java二维数组制作图片迷宫 使用如鹏游戏引擎制作窗口界面 附带压缩包下载,解压后双击start.bat启动

    什么是二维数组? 数组当中放的还是数组 int [][] arr=new int[3][2]; 有3个小箱子,每个箱子2个格子. 看结果? int [][] arr=new int[3][2]; Sy ...

  7. Spring框架bean的注解管理方法之一 使用注解生成对象

    首先在原有的jar包: 需Spring压缩包中的四个核心JAR包 beans .context.core 和expression 下载地址: https://pan.baidu.com/s/1qXLH ...

  8. Ajax跨域问题---jsonp

    跨域:跨域名  一个域名下的文件去请求了和他不一样的域名下资源文件,那么就会产生跨域请求 解决跨域问题办法: 1.将要访问的外部资源存到本域名下的一个php文件 2.用flash方式 3.JSONP: ...

  9. 对freescale的mfgtool的ucl2.xml的理解

    转载于此:http://blog.csdn.net/bugouyonggan/article/details/8664898 对于Freescale MFG编程工具控制文件ucl2.xml的分析 为了 ...

  10. LeetCode(153) Find Minimum in Rotated Sorted Array

    题目 Total Accepted: 65121 Total Submissions: 190974 Difficulty: Medium Suppose a sorted array is rota ...