1 条题解

  • 0
    @ 2025-12-10 10:37:26

    题目理解

    游戏中有 nn 个房间,每个房间有一把类型为 r[i]r[i] 的钥匙,还有 mm 条通道连接房间,通过通道 jj 需要类型为 c[j]c[j] 的钥匙。

    玩家从房间 ss 开始,可以收集当前房间的钥匙(如果没收集过),或者使用已有钥匙通过通道。已收集的钥匙可以永久使用。

    对于每个房间 ii,定义 p[i]p[i] 为从房间 ii 出发能够到达的房间数。要求找到所有满足 p[i]p[i] 最小的房间 ii,并用 0/10/1 数组标记。


    关键观察

    1. 可达关系的等价性

    如果房间 uu 能到达房间 vv,且房间 vv 能到达房间 uu,那么它们属于同一个连通分量。但注意:可达关系不一定是对称的。

    2. 钥匙收集的特性

    • 钥匙可以重复使用,永远不会丢弃
    • 收集钥匙只需到达对应房间一次
    • 通道是否可用取决于对应类型钥匙是否已收集

    3. 问题转化

    问题可以看作:对于每个起点 ss,计算在动态收集钥匙的条件下,通过BFS能到达的房间数。


    算法设计

    1. 核心思路:动态BFS与并查集

    使用一种启发式算法,不断合并可达的房间集合:

    • 并查集维护:将可以互达的房间合并到同一个集合
    • 钥匙驱动扩展:当某个集合收集到新的钥匙类型时,尝试通过需要该钥匙的通道合并其他集合
    • 迭代收敛:反复进行上述过程,直到没有新的合并发生

    2. 算法步骤

    步骤 1:初始化

    // 每个房间初始化为独立的连通分量
    for (int i = 0; i < n; i++) {
        id[i] = i;  // 并查集初始化
    }
    

    步骤 2:BFS扩展过程

    对每个未处理的连通分量进行扩展:

    1. 起点选择:选择一个连通分量的代表房间作为起点
    2. BFS模拟
      • 维护当前已收集的钥匙集合
      • 维护等待队列:可以到达但需要特定钥匙的房间
      • 当收集到新钥匙时,激活对应的等待队列
    3. 结果记录:记录该连通分量可达的房间集合和大小

    步骤 3:合并与优化

    • 如果某个房间在BFS中被访问,但它属于另一个连通分量,则合并这两个连通分量
    • 使用标记数组避免重复访问
    • 使用桶(bin)数据结构高效管理需要特定钥匙的等待房间

    步骤 4:迭代处理

    重复执行步骤2-3,直到所有连通分量都被正确处理且没有新的合并发生。

    步骤 5:结果计算

    • 统计每个连通分量的大小(即 p[i]p[i] 值)
    • 找到最小的大小值
    • 标记所有属于最小连通分量的房间

    算法正确性

    1. 完备性保证

    算法通过迭代处理所有连通分量,确保:

    • 每个房间的可达集合都被正确计算
    • 钥匙的传递和通道的使用被充分考虑

    2. 合并的正确性

    如果房间 uu 能到达房间 vv,且它们属于不同的连通分量,合并它们是合理的:

    • 合并后,从 uu 出发可以到达 vv 所在连通分量的所有房间
    • 反之,从 vv 出发也能到达 uu 所在连通分量的所有房间

    3. 终止性

    由于房间数量有限,每次迭代至少合并两个连通分量或完成一个分量的处理,算法必然在有限步骤内终止。


    复杂度分析

    时间复杂度

    • 最坏情况O(n2)O(n^2),当所有房间都互相可达时
    • 实际性能:通过启发式合并和优化,在大多数情况下接近 O(nlogn)O(n \log n)
    • 通道处理:每条通道最多被处理一次,O(m)O(m)

    空间复杂度

    • 邻接表存储O(n+m)O(n + m)
    • 并查集与标记数组O(n)O(n)
    • 桶数据结构O(n)O(n),用于管理需要特定钥匙的等待房间

    实现细节

    1. 数据结构设计

    vector<int> id;      // 并查集
    vector<bool> ok;     // 连通分量是否已处理
    vector<bool> vst;    // 访问标记
    vector<bool> getk;   // 已收集的钥匙标记
    vector<vector<int>> bin;  // 按钥匙类型分组的等待房间
    

    2. 关键函数

    • BFS扩展:模拟从起点出发的钥匙收集和房间访问过程
    • 连通分量合并:当发现可达的其他连通分量时进行合并
    • 迭代控制:重复执行直到没有新的合并发生

    3. 优化技巧

    1. 延迟处理:将需要特定钥匙的房间暂存,待收集到对应钥匙时再处理
    2. 状态复用:合并连通分量时复用已计算的可达集合
    3. 增量更新:只处理新收集的钥匙和对应的通道

    算法标签

    • 基环树
    • 广度优先搜索
    • 并查集
    • 启发式合并

    总结

    本题通过巧妙的BFS模拟和并查集合并,解决了在动态收集钥匙条件下的房间可达性问题。算法虽然在最坏情况下复杂度较高,但通过多种优化技术,在实际数据上表现良好,能够处理 n,m3×105n, m \leq 3 \times 10^5 的大规模数据。

    • 1

    信息

    ID
    5963
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    10
    已通过
    1
    上传者