小阳数数

小阳数数
描述
武林内纷乱不断,各地都自立门派,门派的人为了识别门内弟子,给了每个人一块令牌,这个令牌有个神奇的地方:门派内的弟子的令牌不一定相同。
下面是他们的识别规则:
每个人的令牌都是一串数字,如果两个人的令牌有相似的地方,即有相同的数字,那就属于同一个门派,特别的,如果两个人没有相同的数字,但是这个两个人都和另一个人有相同的数字,那么这三个人同属一个门派,现在有一个任务,给你n个令牌,让你认出有多少个门派?
输入格式
第一行 输入一个t,代表数据组数(1<=t<=10)
第二行 输入一个n,代表n块令牌 (1<=n<=1000)
下面n行,每行一个数字序列,(1<=len<=1000)
输出格式
有t行,每行一个数,代表有这组数据有多少个门派
样例输入
2
3
13579
2468
12
5
12
23
34
5
5678
样例输出
1
2
提示
3
13579
2468
12
这里答案应该是1,因为第一个人和第二个人同时和第三个人有关系
题解:先记录每个字符第一次出现在哪个字符串里,所以就可以设置一个数组,数组初始化为-1,如果第一次出现字符,就让该数组指向这个字符串,如果数组的值不再为-1了,就代表这个字符在前面已经出现过了,我们递归寻找到这个字符第一次出现的集合(第一次出现该字符的字符串对应的编号),和当前字符串的比较,看是否在同一集合中,不在同一集合就合并

#include<bits/stdc++.h>
using namespace std;
int father[1000 + 10];
int f[1000 + 10];
int t, n;
void init() {
 for (int i = 1; i <= n; i++)
  father[i] = i;
}
int find(int v) {//递归+路径压缩 
 if (father[v] == v)
  return v;
 else
  return father[v] = find(father[v]);
}
int main() { 
 char str[1000 + 10];
 cin >> t;
 while (t--) {
  memset(f,-1,sizeof(f));
  cin >> n;
  init();
  for (int i = 1; i <= n; i++) {
   scanf("%s", str);
   for (int j = 0; j < strlen(str); j++) {
    int m = str[j] - '0';//字符转数字 
    if (f[m] == -1)
     f[m] = i;/*如果这个数字是第一次出现,就指向当前这个字符,i表示 */ 
    else {        /*当前第几个字符串*/ 
     int fa = find(i);//第几个字符串 
     int fb = find(f[m]);//递归寻找当前这个数属于哪个集合,找它的根结点 
     if (fa != fb)//如果不在一个集合中 
      father[fb] = fa;//把这个字符串的编号(也就是第几个)也放到 
        }                   //集合里,即合并两个子集和 ,这里也可以用一个
                         //merge函数来合并 
   }
  }
  int ans = 0;
  for (int i = 1; i <= n; i++) {
   if (father[i] == i)
    ans++;
  }
  printf("%d\n",ans);
 }
}

本菜鸡学了一天并查集,还是有些懵,应该是智商问题了,菜鸡叹息啊…
若有错误,欢迎各位大佬指正!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值