hdu 杭电 2473 Junk-Mail Filter

来源:互联网 发布:淘宝上的黑科技产品 编辑:程序博客网 时间:2024/05/16 00:57
题意:输入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;}

 

 

 

0 0
原创粉丝点击