首页 > 试题广场 >

隐匿社交网络

[编程题]隐匿社交网络
  • 热度指数:3022 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 1024M,其他语言2048M
  • 算法知识视频讲解
\hspace{15pt}牛客网有一个名为牛爱网神秘的入口。这天,牛可乐正在策划牛爱网的全新社交活动。
\hspace{15pt}每个人的账号在初始时都会被分配一个权重,第 i 个账号的权重为 w_i。对于任意的两个账号 ij,如果权重满足 (w_i \operatorname{and} w_j) \geqq 1,那么就会被分配到同一个社交网络。
\hspace{15pt}现在,牛可乐已经为 n 个账号分配了权重,他想知道,包含账号数量最多的社交网络中,包含多少个账号。
\hspace{15pt}牛爱网的日常维护工作忙坏了牛可乐,请你帮帮他。

\hspace{15pt}其中,\operatorname{and} 表示按位与运算。如果您需要更多位运算相关的知识,可以参考 OI-Wiki的相关章节

输入描述:
\hspace{15pt}每个测试文件均包含多组测试数据。第一行输入一个整数 T\left(1\leqq T\leqq 10^5\right) 代表数据组数,每组测试数据描述如下:

\hspace{15pt}第一行输入一个整数 n \left(1 \leqq n \leqq 10^5\right) 代表账号数量。
\hspace{15pt}第二行输入 n 个整数 w_1, w_2, \dots, w_n \left(1 \leqq w_i \leqq 10^{18}\right) 代表账号权重。

\hspace{15pt}除此之外,保证单个测试文件的 n 之和不超过 10^5


输出描述:
\hspace{15pt}对于每组测试数据,新起一行。输出一个整数,代表包含账号数量最多的社交网络中,包含的账号数量。
示例1

输入

2
5
2 1 6 7 16
2
2 16

输出

4
1

说明

\hspace{15pt}对于第一组测试数据,连接示意图如下图所示:
社交网络
参考别人的思路写了一个版本。打算使用并查集再写一个版本

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class Main {

    /**
     * 合并社交圈,计算最大社交圈的大小
     * 使用位运算表示用户的兴趣标签,通过或运算合并有共同兴趣的社交圈
     * 
     * @param interests 每个用户的兴趣标签数组(用long的二进制位表示)
     * @param userCount 用户数量
     */
    public static void mergeSocialCircles(long[] interests, int userCount) {
        // 使用Map表示社交圈:key为社交圈的标签(所有用户兴趣的或运算结果),value为该社交圈的用户数量
        Map<Long, Integer> socialCircles = new HashMap<>();
        int maxCircleSize = 0; // 记录最大社交圈的大小
        
        for (int i = 0; i < userCount; i++) {
            long currentInterest = interests[i];
            long mergedInterest = currentInterest; // 合并后的兴趣标签
            int mergedCount = 1; // 合并后的用户数量,初始为当前用户自己
            
            // 遍历现有社交圈,查找与当前用户有共同兴趣的圈子
            // 注意:这里使用临时数组来避免在遍历时修改Map
            Long[] existingCircles = socialCircles.keySet().toArray(new Long[0]);
            
            for (Long circleInterest : existingCircles) {
                // 检查当前用户兴趣与社交圈兴趣是否有交集(按位与结果不为0)
                if ((currentInterest & circleInterest) != 0) {
                    // 合并兴趣标签(按位或)
                    mergedInterest |= circleInterest;
                    // 累加用户数量
                    mergedCount += socialCircles.get(circleInterest);
                    // 移除被合并的社交圈
                    socialCircles.remove(circleInterest);
                }
            }
            
            // 将合并后的社交圈加入Map
            socialCircles.put(mergedInterest, mergedCount);
            // 更新最大社交圈大小
            maxCircleSize = Math.max(maxCircleSize, mergedCount);
        }
        
        System.out.println(maxCircleSize);
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // 读取测试用例数量
        int testCaseCount = scanner.nextInt();
        
        for (int i = 0; i < testCaseCount; i++) {
            // 读取当前测试用例的用户数量
            int userCount = scanner.nextInt();
            long[] interests = new long[userCount];
            
            // 读取每个用户的兴趣标签
            for (int j = 0; j < userCount; j++) {
                interests[j] = scanner.nextLong();
            }
            
            // 处理当前测试用例
            mergeSocialCircles(interests, userCount);
        }
        
        scanner.close();
    }
}


发表于 2025-09-10 11:14:51 回复(0)
java实现
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        int t = in.nextInt();
        for(int i = 0; i < t; ++i) {
            int n = in.nextInt();
            int maxCount = 1;
            long[] weights = new long[n];
            Map<Long, Integer> nets = new HashMap<>();

            for(int j = 0; j < n; ++j) {
                weights[j] = in.nextLong();
            }
            nets.put(weights[0], 1);
            for(int j = 1; j < n; ++j) {
                long newWeight = weights[j];
                int newCount = 1;
                List<Long> oldWeights = new ArrayList<>();
                for(Map.Entry<Long, Integer> net : nets.entrySet()) {
                    if((weights[j] & net.getKey()) != 0) {
                        newWeight |= net.getKey();
                        newCount += net.getValue();
                        oldWeights.add(net.getKey());
                    }
                }
                for(int k = 0; k < oldWeights.size(); ++k) {
                    nets.remove(oldWeights.get(k));
                }
                nets.put(newWeight, newCount);
                maxCount = Math.max(maxCount, newCount);
            }
            System.out.println(maxCount);
        }
    }
}

发表于 2025-07-28 18:51:53 回复(0)