怀抱观古今,寝食展戏谑。这篇文章主要讲述*HDU - 2473Junk-Mail Filter (并查集--删点操作)相关的知识,希望能为你提供帮助。
题干:
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.
【*HDU - 2473Junk-Mail Filter (并查集--删点操作)】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
解题报告:
并查集删点问题,虚拟一个节点,f数组开到n+m,用来找real点的父节点,real开到n,用来存输入数据的真实值(输入的也都是小于n的,但是real数组可以将其映射到> n上,换句话说,real的下标一定小于n(此题取不到等号),但是real的内容可以大于n,其实也就是 可能是那个从n+1开始的id值)。注意一些细节以及背过这一个模板即可。
ac代码:
#include< iostream>
#include< cstdio>
#include< algorithm>
#include< cstring>
const int MAXn = 1e5 + 5; //点数
const int MAXm = 1e6 + 5; //指令数
using namespace std;
int n,m;
int cnt,id;
char op[5];
int f[MAXn+MAXm+5];
int real[MAXn+5]; //real不需要开到MAXm!!
int bk[MAXn+MAXm+5];
int getf(int v)
if(f[v]!=v)
f[v]=getf(f[v]);
return f[v];
void init()
cnt=0;
id=n+1;
for(int i = 1; i< =n; i++)
real[i]=i;
f[i]=i;
memset(bk,0,sizeof(bk) );
void merge(int u,int v)
int t1=getf(u);
int t2=getf(v);
if(t1!=t2) f[t2]=t1;
void del(int u)
real[u]=id;
f[id]=id; //必须要有,因为f数组只赋值到n,所以要赋值!
id++;
int main()
int u,v;
int iCase=0;
while(~scanf("%d %d",& n,& m) )
if(m==0 & & n==0) break;
init();
while(m--)
scanf("%s",op);
if(op[0]==M)
scanf("%d %d",& u,& v);
merge(real[u],real[v]);
else
scanf("%d",& u);
del(u); //?有疑问? //必须u!!不能real[u]! 想想也知道啊因为del里面real[i]其中i要< n的(因为开的数组real[]开到了n,就是 记录输入的点的真实值,而输入的点最大是n)!所以你传的i肯定要< n啊所以不能是real[u]!
//其实如果 传real[u],你想找到他就需要real[real[u]]了!显然不符合了。。整个结构都改变了,因为你可能两层real嵌套就可能三层四层、、代码没法实现了就。
for(int i = 0; i< n; i++) //此题规定了!从 0 开始!
if(bk[getf(real[i] ) ] ==0) //别忘加getf!!
bk[getf(real[i] ) ]=1;
cnt++;
printf("Case #%d: %d\\n",++iCase,cnt);
return 0 ;
ac代码2:(可以再看看?)
分析:这道题是一道典型的并查集的题目,关键是节点从集合中删除的s操作
这里使用了节点数的的下标+n作为父节点,这个位置只是标记父节点,并没其他含义,等于是虚拟的节点。
这样当删除一个节点时只用从这个节点中拿出来让其父节点重新放在一个虚拟的位置,即下标从n+n开始向后找。
最后是查找独立特点的集合。将这些父节点放在一个长度为n的num的数组中,里边放置的每个节点对应的父节点的位置,
然后对这个数组排序,找出其中不同父节点的数目即集合的个数。
#include < iostream>
#include < stdio.h>
#include < algorithm>
#define MAXNUM1 100005
#define MAXNUM2 1000005
using namespace std;
int f[MAXNUM1*2+MAXNUM2],num[MAXNUM1];
int getf(int a)
if(f[a]==a)return a;
else return f[a]=getf(f[a]);
int main()
int n,m,ca,x,y,total;
char op[3];
ca = 0;
while(scanf("%d%d",& n,& m)!=EOF& & n)
for(int i=0; i< n; i++)f[i]=i+n;
for(int i=n; i< =n+n+m; i++)f[i]=i;
total =推荐阅读
- POJ - 2236Wireless Network (并查集)
- POJ - 3250 Bad Hair Day (单调栈)
- *HDU - 1506POJ - 2559Largest Rectangle in a Histogram(单调栈或动态规划)
- CF#459 A Pashmak and Garden(水题)
- HDU - 1870愚人节的礼物(水题模拟 思想类似于栈())
- CF#-931A Friends Meeting(思维)
- 什么是真正的敏捷开发(敏捷开发与瀑布开发有何不同)
- CF#468 div2 D. Peculiar apple-tree(思维)
- HDU - 1301Jungle Roads(并查集+最小生成树)(内附最小生成树两种算法 克鲁斯特尔算法&&普里姆算法)