吉首大学新星杯——小阳数数

这道题说来和我颇有故事,最早是在一个月前的吉首大学同步赛遇到的,可见我博客 传送门
在这里插入图片描述
这是我当时写的博客的截图= =我那天晚上和学长吃饭时也被学长说服了,认为并查集写不了… … 然后今天下午的牛客上拉出了重现赛,我看了一下这道题,突然觉得可以用并查集写。事实证明我的感觉是对的在这里插入图片描述

先上原题:

链接:传送门

武林内纷乱不断,各地都自立门派,门派的人为了识别门内弟子,给了每个人一块令牌,这个令牌有个神奇的地方,
门派内的弟子的令牌不一定相同,
下面是他的识别规则:
每个人的令牌都是一串数字,如果两个人的令牌有相似的地方,即有相同的数字,那就属于同一个门派,特别的,
如果两个人没有相同的数字,但是这个两个人都和另一个人有相同的数字,那么这三个人同属一个门派,现在有一个任务
,给你n个令牌,让你认出有多少个门派
例如 
3
13579
2468
12
这里答案应该是1,因为第一个人和第二个人同时和第三个人有关系
输入描述:

第一行  输入一个t,代表数据组数(1<=t<=10)
第二行 输入一个n,代表n块令牌   (1<=n<=1000)
下面n行,每行一个数字序列,(1<=len<=1000)

输出描述:

有t行,每行一个数,代表有这组数据有多少个门派

示例1
输入
2
3
13579
2468
12
5
12
23
34
5
5678

输出
1
2

并查集解题思路: 先看题意,很简单,即有相同数字的是一个门派,也就是可以建立集合关系。然后我开了一个二维数组tong[i][j]来记录第i个人包含0~9中的哪些数字,然后就是暴力建立关系、找关系了。
AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <cmath>
#include <algorithm>
using namespace std;
#define ll long long
char p[1005];
int pre[1005];
int t[1005];
int tong[1005][15];
int find(int x)//查找根结点
{
    int r = x;
    while (r != pre[r])
        r = pre[r];
    int k = x, temp;
    while (pre[k] != r)//压缩路径
    {
        temp = pre[k];
        pre[k] = r;
        k = temp;
    }
    return r;
}
void mix(int x, int y)//建立x、y关系
{
    int fx = find(x);
    int fy = find(y);
    if (fx != fy)
        pre[fx] = fy;
    return;
}
int main()
{
    int time;
    cin >> time;
    while (time--)
    {
        memset(tong, 0, sizeof(tong));
        memset(t, 0, sizeof(t));
        memset(pre, 0, sizeof(pre));
        int n;
        cin >> n;
        for (int i = 1; i <= n; i++)
            pre[i] = i;
        for (int i = 1; i <= n; i++)
        {
            memset(p, '\0', sizeof(p));
            cin >> p;
            for (int j = 0; j < strlen(p); j++)
                tong[i][p[j] - '0'] = 1;
        }
        for (int i = 1; i <= n; i++)
            for (int j = i + 1; j <= n; j++)
                for (int l1 = 0; l1 <= 9; l1++)
                    if (tong[i][l1] == tong[j][l1] && tong[i][l1])
                        mix(i, j);
        int ans = 0;
        for (int i = 1; i <= n; i++)
            t[find(i)] = 1;
        for (int i = 1; i <= n; i++)
            if (t[i])
                ans++;
        cout << ans << endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hesorchen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值