您的位置:首页 > 大数据 > 人工智能

HDU 2473 Junk-Mail Filter 并查集 删点

2015-07-31 11:27 309 查看
原题: http://acm.hdu.edu.cn/showproblem.php?pid=2473

题目:

Junk-Mail Filter

Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 7582 Accepted Submission(s): 2392

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 ≤ 105 , 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

思路:

对于给定数据,有联系的属于一个集合,也可以将一些点剔出集合,最后共有多少个集合。

相比于上一题,这次多了个删点操作。

这里引入rep数组修改原来删除点的位置。用一个全新的点去代替被删的点,建立新的集合关系。

代码:

#include <iostream>
#include"cstdio"
#include"string.h"
#include"stdlib.h"
using namespace std;

//如果10^6操作丧心病狂全是删点,那么会有11*10^6个点
const int N = 1100005;
int NN;
int fa
;
int rep
;
int flag
;    //是否被访问过
int cs=1;
int n,t;

void init()
{
NN=n;
for(int i=0; i<N; i++)
{
fa[i]=i;
rep[i]=i;   //每个点原先都是它本身
}
memset(flag,0,sizeof(flag));
}

int Find(int x)
{
int temp=x;
while(fa[temp]!=temp)
{
temp=fa[temp];
}
int i=x;
int j;
while(fa[i]!=i)
{
j=fa[i];
fa[i]=temp;
i=j;
}
return temp;
}

void mix(int x,int y)
{
int  tx=Find(x);
int  ty=Find(y);
if(tx!=ty)
{
fa[tx]=ty;
}
}

void printans()
{
int cut=0;
for(int i=0; i<n; i++)
{
int tt=Find(rep[i]);
if(flag[tt]==0)
{
flag[tt]=1;
cut++;
}
}
printf("Case #%d: %d\n",cs,cut);
cs++;
}

int main()
{
while(scanf("%d %d",&n,&t)!=EOF)
{
if(n==0&&t==0)  break;
getchar();
init();
char bz;        //读取步骤
for(int i=0; i<t; i++)
{

int a,b;    //读取步骤需要的值
scanf("%c",&bz);
if(bz=='M')
{
scanf("%d %d",&a,&b);
mix(rep[a],rep[b]);
}
//如果某个点要删除,我们只需要用另一个未使用过的点去代替它
else if(bz=='S')
{
scanf("%d",&a);
rep[a]=NN;
fa[NN]=NN;
NN++;
}
getchar();
}
printans();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: