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

HDU 2473 Junk-Mail Filter 并查集

2012-09-03 19:37 309 查看
http://acm.hdu.edu.cn/showproblem.php?pid=2473

题意:

  N 是 标号为 0~(N-1)的邮件 M是有M行数据。

  第二行开始为数据 当输入为M时之后跟着的两个编号表示这两封邮件都为一种垃圾邮件。

当输入为S时跟着的一个标号表示这封邮件被误判,这不是封垃圾邮件,而之前与这封邮件同时被判为垃圾邮件的那封邮件还是垃圾邮件。

输出为有多少种邮件(垃圾邮件也分很多种)。

坑爹:

  1.当要将一封垃圾邮件变为普通邮件时,如果在这个垃圾邮件的树中作为根的话,那么变为普通邮件时要将剩余的垃圾邮件重新合并起来。

  2.当要搜索有多少个集合(邮件种类)的时候要查找 father[i] == i 这种有多少个,但如果是 (0-1-2-3-4)(假设根为0),将01234这些点都删除了,

用 father[i] == i 来找集合的话会把前面的 (0邮件)也会算上的。

解法:

  用一个代理的数组(起始跟输入的值一样),访问、删除的时候将real数组的值改变就行了(删除就将real[i]等于代理数组下标为n以后的位置),而合并就用代理数

组进行操作就行了。

  

View Code

#include<iostream>
using namespace std;

const int maxn = 1000000 + 100000 +10;

int real[maxn];
int father[maxn];  //father[x]表示x的父节点
int rank[maxn];     //rank[x]  秩,表示x节点所在树的深度
int save[maxn];
int used[maxn];

void Make_Set()
{
memset(used,0,sizeof(used));
for(int i=0;i<maxn;i++)
{
father[i]=i;    //初始化一开始每个节点的父节点都为本身
rank[i]=1;        //初始化一开始每棵树的深度为1
}
}

int findroot (int a )// 寻找x元素所在的集合也就是找子节点的根节点
{
int k=0;
while ( a != father[a] )
{
save[k++] = a;
a = father[a];
}
for(int i=0;i<k;i++)
father[ save[i] ] = a;
return a;
}

void Union(int x,int y)    //合并两个不相交的集合,x,y分别为两个不同的集合
{
x = findroot(x);
y = findroot(y);
if(x != y)
{
if(rank[x] > rank[y])   //如果x树的深度比y树深,y树接到x树
{
father[y] = x;
}
else if(rank[x] < rank[y])
{
father[x] = y;
}
else if(rank[x] ==rank[y])  //若两树的深度一样
{
father[x] = y;           //则x树接到y树
rank[y]++;              //此时y树的深度+1
}
}
}

int main()
{
int N;
int M;
int k = 1;
while(cin>>N>>M,N+M)
{
Make_Set();
int i;
for(i =0; i<N;i++)         // 让real 和 father 一一对应
{
real[i] = i;
}
int count = N - 1;           // 要删除结点时在father数组中的最后一位给real[del]一个新的代理
while(M-- )
{
char ch;
cin>>ch;
if(ch == 'M')
{
int x;
int y;
cin>>x>>y;
Union(real[x],real[y]);
}
if(ch == 'S')
{
int del;
cin>>del;
real[del] = ++count ;
}
}

int rootcount = 0;
//int max = N;
/*if(count > N - 1)
{
max = count;
}*/
for(i =0; i<N; i++)
{
int a=findroot(real[i]);
if(!used[a])
{
//printf("%d***\n",a);
used[a]=1;
rootcount++;
}
}
cout<<"Case #"<<k++<<": "<<rootcount<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: