校赛 (离散化 + 并查集)

题目描述

狗逼喵养了只小喵呜,编号1-N。第i只小喵呜懂M_i种语言。

俗话说得好,语言不通怎么啪啪啪,所以只有当两只小喵呜懂相同的语言的时候他们才能交流才能成为好朋♂友♀。

当然就算两只小喵呜不懂同一种语言也可以请其他小喵呜当翻译。换句话说,小喵呜A和小喵呜B可以成为好朋友的前提是存在一个序列A,T_1,T_2,…..,T_k,B(k>=0),其中A和T_1都会说某一种语言,T_1和T_2也都会说某一种语言…..,并且T_k和B会说某一种语言。

狗逼喵希望他的小喵呜都能成为好朋♂友♀,于是他决定买一些技能书教某些小喵呜一些语言。但是狗逼喵最近比较穷他想知道他最少需要买多少本书。(注:一本书仅能对一只喵呜使用,并且只能教会这只喵呜一种语言)

输入格式

第一行输入一个整数T,表示有T组数据,对于每组数据,第一行输入一个n表示有n(n<=10000)只小喵呜,接下来输入n行。第i行先输入一个M_i(0<=M_i<=10)表示第i只小喵呜懂M_i种语言。接下来输入M_i个数表示这只小喵呜懂的语言编号(1<=编号<=10^7)

输出

每组数据输出一个数,表示狗逼喵最少要买多少本书。

样例输入

1

3

1 1

2 1 2

1 3

样例输出

1

思路:利用一个record的数组来记录其中一只会第i种语言的猫的编 号。然后并查集。但是注意,因为猫会的语言的编号是1~10^7,但是总共有10^4只猫,每只猫至多会10种语言。所以总共可能出现的语言数最多为10^5。所以需要离散化。

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
using namespace std;

struct Miao {
    int cat;
    int lantot;
    int language[11];
}M[100005];
int al;
int reflex[100005];//离散化
int record[100005];
int f[100005];

int Find(int x) {
    if (f[x] == x) return x;
    return f[x] = Find(f[x]);
}

int BinarySearch(int x) {
    int l = 0, r = al;
    if (reflex[r] == x) return r;
    while (r - l > 1) {
        int m = (l + r) >> 1;
        if (reflex[m] > x)
            r = m;
        else
            l = m;
    }
    return l;
}

int main() {
    int t;
    scanf("%d", &t);
    for (int ca = 1; ca <= t; ca++) {
        int n, all = 0;
        scanf("%d", &n);
        al = 0;
        for (int i = 1; i <= n; i++) {
            int m;
            scanf("%d", &m);
            M[i].lantot = 0;
            M[i].cat = i;
            for (int j = 1; j <= m; j++) {
                int x;
                scanf("%d", &x);
                M[i].language[M[i].lantot++] = x;
                reflex[all++] = x;
            }
        }

        //离散化
        sort(reflex, reflex + all);
        for (int i = 1; i < all; i++)
            if (reflex[i] != reflex[al]) reflex[++al] = reflex[i];

        //并查集
        for (int i = 1; i <= n; i++) f[i] = i;
        memset(record, 0, sizeof(record));

        for (int i = 1; i <= n; i++) {
            for (int j = 0; j < M[i].lantot; j++) {
                int x = BinarySearch(M[i].language[j]) + 1;
                if (record[x] == 0)
                    record[x] = M[i].cat;
                f[Find(M[i].cat)] = Find(record[x]);
            }
        }

        for (int i = 1; i <= n; i++) f[i] = Find(i);
        sort(f + 1, f + n + 1);

        int x = f[1];
        int need = 0;

        for (int i = 1; i <= n; i++) {
            if (f[i] != x) {
                need++;
                x = f[i];
            }
        }
        printf("%d\n", need);
    }
    return 0;
}
时间: 2024-11-13 10:43:27

校赛 (离散化 + 并查集)的相关文章

油菜花王国——杭电校赛(并查集)

油菜花王国 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1609    Accepted Submission(s): 411 Problem Description 程序设计竞赛即将到来,作为学校ACM集训队主力,小明训练一直很努力.今天天气不错,教练也心情大好,破例给各位队员放假一天,小明就骑着自己的小电驴到郊外踏青去了. 出城不

Poj 1733 Parity Game(离散化+并查集)

 题目大意:给出n个数字,m个区间内的数字和的奇偶性,询问从哪句话开始出现错误. 1.对于给定区间[l , r]的奇偶性,可以转化为[1. l-1]和[1, r]的奇偶性"关系",这样就可以用带权并查集来做了,权值为当前结点与根节点的奇偶性关系,每次查询如果l,r根结点相同,那么判断这句话是否正确,如果根节点不同,那么合并. 2.由于这道题数据量很大,但是查询只有m(m<=5000)所以要先将数据离散化.对于离散化,有两种方法,一种是考虑元素大小相对关系的,一种是不需要考虑元

acdream 1725 哗啦啦的小彭玉染色问题 离散化并查集

哗啦啦的小彭玉染色问题 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acdream.info/problem?pid=1725 Description 哗啦啦,哗啦啦~ 小彭玉很开心,拿着一堆海报就开始宣传明天要开始的哗啦啦大会了~ 小彭玉很可爱,他的海报都是五颜六色的~ 哗啦啦,哗啦啦~ 小彭玉在一个巨大的宣传栏上贴了一大堆海报! “真是好看呢!”,唐老师说道. 唐老师这时,就想出了一个题目,“这面宣传栏,最后能看见多少颜色呢?” 狗

Hdu 1856(离散化+并查集)More is better

题意:一些人遵循朋友的朋友也是朋友原则,现在找出最大的朋友圈, 因为人的编号比较大,但是输入的数据最多是10w行,所以可得出最多也就20w人,所以可以进行一下离散化处理,这样数据就会毫无压力 //////////////////////////////////////////////////////////////////// #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h

2018 FJUT acm校赛 b题 第二集:以后我就叫你小蛤了

第二集:以后我就叫你小蛤了 TimeLimit:1000MS  MemoryLimit:128MB 64-bit integer IO format:%lld Problem Description "小蛤啊,对了以后我就叫你小蛤了,你给的题完全没有难度啊" "哼,你别得意,让你碰巧做出来了而已,接下来这题你绝对不可能做出来的,你要是做出来了balabalabala...." "行了行了,快说题目吧,我时间宝贵啊!" 小A心急如焚,想尽快知道小C

POJ - 1733 离散化 并查集

题意:求问数列区间奇偶信息正确与否 和上一题一样(甚至弱化),加个离散就ok啦 #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<string> #include<vector> #include<stack> #in

NOI 2015 DAY1 T1 程序自动分析 并查集+离散化

题意:暂且并没有链接 方法:并查集+离散化 解析: 国赛这道普及组难度的题我都不好意思写题解, 这道题的题意非常明了,一眼题.. 其实就是把所有的要求sort一下,把令xi=xj的条件放在前面,令xi!=xj的条件放到后面就行了. 然后我们对于n个询问,先把所有的i,j离散化,这里我偷懒用了map 然后只需要将所有xi=xj的部分加到并查集里. xi!=xj的部分看一下二者的祖先相不相同就行了,不相同就判断下一个,相同输出no: 代码: 这道题贴代码真是不好意思- - #include <map

poj1733(种类并查集+离散化)

题目链接: http://poj.org/problem?id=1733 题意: 输入n表示有一个长度为n的0,1字符串, m表示接下来有m行输入, 接下来的m行输入中x, y, even表示第x到第y个字符中间1的个数为偶数个, x, y, odd表示第x到第y个字符中间1的个数为奇数个, 若m句话中第k+1是第一次与前面的话矛盾, 输出k; 思路: 若x, y之间1的个数为偶数个, 那么1~x 与1~y中1的个数同奇偶性, 反之则异奇偶性, 我们可以将其理解为若输入x, y, even, 即

【并查集+离散化】BZOJ4195- [Noi2015]程序自动分析

[题目大意] 在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足. 考虑一个约束满足问题的简化版本:假设x1,x2,x3,…代表程序中出现的变量,给定n个形如xi=xj或xi≠xj的变量相等/不等的约束条件,请判定是否可以分别为每一个变量赋予恰当的值,使得上述所有约束条件同时被满足.例如,一个问题中的约束条件为:x1=x2,x2=x3,x3=x4,x1≠x4,这些约束条件显然是不可能同时被满足的,因此这个问题应判定为不可被满足. 现在给出一些约束满足问题,请分别对它们进行判定.