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

hdu 杭电 2473 Junk-Mail Filter

2012-08-31 18:47 351 查看
题意:输入N M,N代表开始时存在N种不同的集合数从0~(N-1),M代表有M行输入。

M X Y 代表X与Y的内容相同并在一个集合中。

S X 代表要从X当前的集合中脱离出来成为一个独立的集合。

最后要求的是不同集合数的个数。

输入数据比较大,这题最好用scanf();printf()输入 输出。

解法:并查集,在集合中删除元素,用N~N+N+M作为虚拟节点。

注意:并查集,找父节点时用压缩路径的方法,本人一开始用了递归,结果不言而知的wa。

代码:

View Code

#include<iostream>
#include<algorithm>
using namespace std;
const int m=1400000;
int father[m],sign[m],ran[100009]; //father[]记录每一个点的父节点

int find(int x)       //压缩路径其中的奥妙自己领会
{
int i=0;
while(x!=father[x])
{
sign[i++]=x;
x=father[x];
}
for(;i>0;i--)
{
father[sign[i-1]]=x;
}
return x;

}

void uion(int x,int y)
{
x=find(x);
y=find(y);
if(x!=y)
father[y]=x;
}

int main()
{
int n,m;
int k=1;
while(scanf("%d%d",&n,&m))
{
if(n==0&&m==0)break;
int i;

for(i=0;i<n;i++)    //虚拟节点的应用
{
father[i]=i+n;    //将0~n-1每一虚拟一个父子节点,n~n+n+m父子节点为自身,如:当n=3,m=3时
//father[i]:3 4 5 3 4 5 6 7 8 9
}                    //        i:0 1 2 3 4 5 6 7 8 9
for(i=n;i<=2*n+m;i++)
{
father[i]=i;
}

int step=2*n;

char c;
int a,b;
for(i=0;i<m;i++)
{
cin>>c;
if(c=='M')
{
scanf("%d%d",&a,&b);
uion(a,b);
}
else
{
scanf("%d",&a);
father[a]=step++;
}
}

for(i=0;i<n;i++)
{
ran[i]=find(i);
}

sort(ran,ran+n);

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