您的位置:首页 > 其它

天下大乱

2015-08-25 08:39 344 查看
时间限制: 1 Sec

内存限制: 128 MB

提交: 132

解决: 31

[提交][状态][讨论版]

题目描述

乱世天下,诸侯割据。每个诸侯王都有一片自己的领土。但是不是所有的诸侯王都是安分守己的,实力强大的诸侯国会设法吞并那些实力弱的,让自己的领土面积不断扩大。而实力弱的诸侯王为了不让自己的领土被吞并,他会联合一些其他同样弱小的诸侯国,组成联盟(联盟不止一个),来共同抵抗那些强大的诸侯国。 强大的诸侯国为了瓦解这些联盟,派出了最优秀的间谍来离间他们,使一些诸侯国退出联盟。最开始,每个诸侯国是一个联盟。

有两种操作

1、U x y 表示x和y在同一个联盟。

2、D x 表示x退出联盟。

输入

多组测试数据

第一行两个数,n和m(1 ≤ n≤ 10^5, 1 ≤ m ≤10^5),分别表示诸侯国的个数和操作次数。

接下来有m行操作

输出

输出联盟的个数

样例输入

10 1

U 0 9

5 7

U 0 1

U 1 2

U 0 3

D 0

U 1 4

D 2

U 0 2

样例输出

9

2

刚看到这道题的时候想着so easy,删除元素时候直接写了

else if(s=='D')
{
        scanf("%d",&a);
        per[a]=a;
}


根本没想到如果删除的是根节点的话整个集合就散了。。。后来研究了别人的,说是用虚根,研究了好久终于懂

就像别人说的送便当,便当从0之n-1编号,用w数组记录存放这些便当的盒子编号,当然最初编号为几的食物就放在几号盒子中,有些是要送给同一个人的,当然就把这些合并在一起,而对于某些要退食物的,就要把该食物编号从组织中删除,删除时候用w数组将该食物放在一个新盒子中,而原来放该食物的盒子不予以处理,以免打乱他们的关系。最后寻找这些食物各自的根节点,若该根节点记录过,跳过以免重复,没有记录过便ans+1,计算总组数的数目

#include<cstdio>
#include<cstring>
int n,m,per[12],w[100020],mark[12];//w需要定义的大些,它记录的是每个数据存放的真实位置
void init()//初始化
{
    for(int i=0;i<n;i++)
    {
        per[i]=i;
        w[i]=i;
    }
}
int find(int x)//找根节点
{
    int r=x;
    while(r!=per[r])
        r=per[r];
    return r;
}
void join(int a,int b)//合并
{
    int la=find(a);
    int lb=find(b);
    if(la!=lb)
        per[la]=lb;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        int ans=0,a,b,t=n;//最初的虚节点记录为n
        char s;
        init();
        while(m--)
        {
            getchar();//下面要输入字符,吸收回车键
            scanf("%c",&s);//不许再用gtchar了,整型数据能够分辨
            if(s=='U')
            {
                scanf("%d%d",&a,&b);
                join(w[a],w[b]);//不可以写作a,b,需要合并其真实的位置
            }
            else if(s=='D')
            {
                scanf("%d",&a);
                w[a]=t;//其真实位置,就像之前说的便当存放的真实盒子
                per[t]=t;//父节点变为自己
                t++;//下一个虚根
            }
        }
        memset(mark,0,sizeof(mark));
        for(int i=0;i<n;i++)
        {
            if(mark[find(w[i])]==0)//此根节点没有使用过
            {
                mark[find(w[i])]=1;//使用后记录一下
                ans++;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: