蓝桥杯2024省赛B组传送阵问题:环检测算法精解
一、问题背景
题目模拟了一个传送阵系统,每个传送点指向另一个传送点,形成若干传送环。要求找出通过添加最少的传送通道(最多一条)能够形成的最大传送环的大小。
二、核心算法思路
三、完整代码解析(带注释)
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { ios::sync_with_stdio(false); // 关闭同步提升IO速度 cin.tie(nullptr); int n; // 传送点数量 cin >> n; vector<int> a(n + 1); // 传送目标数组 for (int i = 1; i <= n; ++i) cin >> a[i]; // 环标记数组和环大小记录 vector<int> cycle_id(n + 1, 0); vector<int> cycle_size; int id = 0; // 环编号 // 预处理找出所有环 for (int i = 1; i <= n; ++i) { if (cycle_id[i]) continue; // 已处理过的节点跳过 id++; int cnt = 0, j = i; // cnt记录环大小,j为当前节点 while (!cycle_id[j]) { cycle_id[j] = id; cnt++; j = a[j]; // 移动到下一个节点 } cycle_size.push_back(cnt); // 记录环大小 } // 统计最大环和次大环 int max1 = 0, max2 = 0; for (int sz : cycle_size) { if (sz > max1) { max2 = max1; max1 = sz; } else if (sz > max2) { max2 = sz; } } // 基础结果:最大环+1(如果有次大环)或最大环 int result = (max2 > 0) ? max1 + 1 : max1; // 检查是否有相邻节点在不同环的情况 bool has_adjacent = false; for (int i = 1; i < n; ++i) { if (cycle_id[i] != cycle_id[i + 1]) { has_adjacent = true; break; } } // 如果有相邻节点在不同环,可以合并两个环 if (has_adjacent) { result = max(result, max1 + max2); } cout << result << endl; return 0; }
四、关键算法点详解
环检测算法:通过追踪每个节点的传送路径,标记已访问节点来识别环
环统计优化:维护最大和次大环的大小,为后续优化提供基础
相邻环检测:检查是否存在物理相邻但属于不同环的传送点
结果计算策略:考虑两种优化可能(简单连接和合并相邻环)
五、复杂度分析
时间复杂度:O(n) 每个节点只被处理一次
空间复杂度:O(n) 用于存储环标记和环大小
六、实际应用场景
这种环检测算法广泛应用于:
网络路由检测
内存管理中的循环引用检测
游戏中的传送系统设计
社交网络中的关系环分析
参考:蓝桥杯省赛B组传送阵
原创内容 转载请注明出处