娜娜梦游仙境系列——多民族王国

传送门

娜娜梦游仙境系列——多民族王国

TimeLimit:1000MS  MemoryLimit:64MB
64-bit integer IO format: %lld
已解决 |  点击收藏
Problem Description

娜娜好不容易才回忆起自己是娜娜而不是什么Alice,也回忆起了自己要继续探索这个世界的目标,便偷偷溜出皇宫。娜娜发现这个王国有很多个民族组成,每个民族都有自己的方言,更要命的是这些方面差别还很远,这就导致这个王国的人民交流十分困难。娜娜仔细观察并记录了好久,发现总共有m种不同的语言。

突然娜娜发现前面有一群天才在讨论问题,但是奈何语言问题,导致这群人交流非常吃力。不过幸亏的是,这群天才都有一个特殊的能力,只要消耗一个单位的能量即可完全领悟一门新的语言(妈妈再也不用担心我的四六级托福雅思GRE!)。于是娜娜久违的的好奇心又开始冒泡了,娜娜希望你告诉她,如果知道了每个人会的语言,是否能让这群天才两两直接或者间接的交流呢?所谓间接得交流是指经过若干个人的翻译使两个人得到相互表达的信息。如果不能,至少需要多少能量才能实现呢?

Input

多组数据,首先是一个正整数t(t<=20)

对于每组数据,首先是两个整数n,m(2<=n<=100,1<=m<=100),分别代表人数以及语言的种类数,语言的编号从1~m。

接下来是n行,每行对这个人进行描述

首先是一个整数k,表示这个人已经会k门语言,接下来是k个整数,分别是这个人掌握的语言编号。(0<=k<=m)

Output

对于每组数据,输出一个整数,表示使得这群人能够互相直接或者间接交流所需要的最少能量。

SampleInput
2
2 2
1 2
0
5 5
1 2
2 2 3
2 3 4
2 4 5
1 5
SampleOutput
1
0
提示:
样例1中其中第一个人会第二种语言,而第二个人不会任何语言,所以只需要第二个人也学会第二种语言即可交流,所以能量数为1
样例2中有5个人,而且这5个人已经可以相互直接或间接进行交流: 1-2-3-4-5,正好构成一条链。因此不需要继续学习新的语言,能量数为0。
#include <stdio.h>
#include <string.h>
#define MAXSIZE 205

int fa[MAXSIZE],rank[MAXSIZE];

void makeSet(int size)    //为每个数创建集合,指向自己,rank保存秩
{
    int i;
    for(i = 0;i < size;i++)
    {
        fa[i] = i;
        rank[i] = 0;
    }
}

int find(int x)
{      //路径压缩,把所有元素指向根

    return fa[x]==x?x:find(fa[x]);

}

int unionSet(int x, int y)
{  //联合两个集合,返回是否两个不同集合

    if ((x = find(x)) == (y = find(y)))
        return 0;
    if (rank[x] > rank[y])
        fa[y] = x;
    else
    {
        fa[x] = y;
        if (rank[x] == rank[y])
            rank[y]++;
    }
    return 1;
}

int main()
{
    int t,i,j,s,k,mark,ski,n,m,p,q,l,sum;
    while(scanf("%d",&t)==1)
    {
        while(t--)
        {
            scanf("%d %d",&n,&m);
            s=sum=0;
            makeSet(MAXSIZE);
            for(i=1;i<=n;i++)
            {
                scanf("%d",&ski);
                if(ski==0)
                    sum++;
                for(j=0;j<ski;j++)
                {
                    scanf("%d",&k);
                    p=unionSet(k+100,i);   //把语言种类+100放到人物i中
                    if(p==0)              //说明该语言别的人会
                    {
                        q=find(k+100);
                        unionSet(i,q);     //把该人物和能交流的另一个人放入一个集合
                    }
                }
            }
            if(sum==n)           //所有人会的语言为0
                printf("%d\n",n);
            else
            {
                for(i=1;i<=n;i++)
                {
                    if(fa[i]==i)  //根指向自身,所以满足的话就是一个集合,否则是属于别的集合的,即是相关的。
                        s++;
                }
                printf("%d\n",s-1);  //n个集合,只要n-1个边就可以了
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值