• hdu 杭电 2473 JunkMail Filter 果枫


    题意:输入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;
    }
  • 相关阅读:
    剑指offer——从尾到头打印链表节点的值
    1, sync_with_stdio(), tie()的应用
    Python基础1:一些小知识汇总
    HTML
    CSS
    周总结
    十三章
    十二章总结
    十一章总结
    第十一章
  • 原文地址:https://www.cnblogs.com/zgfailmr/p/2665845.html
Copyright © 2020-2023  润新知