当前位置:首页 > 蓝桥杯 > 2016年蓝桥杯省赛B组交换瓶子题解(洛谷P8637)| 解题思路与代码优化

2016年蓝桥杯省赛B组交换瓶子题解(洛谷P8637)| 解题思路与代码优化

3个月前 (09-03)

2016年蓝桥杯省赛B组交换瓶子题解(洛谷P8637)| 解题思路与代码优化 蓝桥杯省赛 并查集 环形结构 洛谷 C++ 第1张

一、题目解读

题目要求将N个瓶子通过交换操作使其编号与位置对应(即每个瓶子指向自身)。每个瓶子初始指向另一个瓶子位置,需计算最小交换次数。例如,当瓶子i指向瓶子j时,交换i与j的位置可使两者指向自身。题目关键在于识别环形结构并计算交换次数。

二、解题思路

并查集(Union-Find)思想优化解题:

1. 将每个瓶子视为节点,初始各节点自成环。

2. 遍历时标记已访问节点,识别出每个连通环(即闭合路径)。

3. 每个环的交换次数为环大小-1(最后一个节点无需交换)。

4. 累加所有非单节点环的交换次数,得到最终结果。

核心在于利用环结构特性减少无效交换计算。

三、解题步骤

1. 输入处理:读取N及每个瓶子的指向位置,存储于bottles数组(1-based索引)。

2. 初始化标记:使用visited数组记录节点是否被遍历。

3. 循环遍历:

    对每个未访问节点i,启动新环遍历。

    通过while循环跟踪链i → bottles[i] →...直至回到起点(形成环)。

    标记路径上所有节点,记录环大小cycleSize。

4. 交换次数计算:若环大小>1,则需cycleSize-1次交换(单节点环无需交换)。

5. 输出结果:累加所有环的交换次数并输出。

四、代码与注释

#include <iostream>
#include <vector>
using namespace std;

int main() {
   int N;
   cin >> N;
   vector<int> bottles(N + 1);  // 使用1-based索引
   vector<bool> visited(N + 1, false);
   
   // 读取输入
   for (int i = 1; i <= N; ++i) {
       cin >> bottles[i];
   }
   
   int swapCount = 0;
   
   // 遍历每个瓶子
   for (int i = 1; i <= N; ++i) {
       if (!visited[i]) {   // 未访问节点为新环起点
           // 开始一个新的环
           int current = i;
           int cycleSize = 0;
           
           // 遍历整个环
           while (!visited[current]) {
               visited[current] = true;  // 标记已访问
               current = bottles[current];  // 跟踪指向节点
               cycleSize++;              // 环大小+1
           }
           
           // 每个大小为k的环需要k-1次交换
           if (cycleSize > 1) {
               swapCount += (cycleSize - 1);
           }
       }
   }
   
   cout << swapCount << endl;
   return 0;
}

注释说明:

● visited数组用于避免重复遍历已处理的环。

● cycleSize记录当前环的节点数,通过累加遍历次数计算。

● 最终交换次数仅累加非单节点环的贡献,避免冗余计算。

五、总结

本解法通过并查集思想将问题转化为环计数,有效降低时间复杂度。关键在于识别闭合路径并优化交换次数计算逻辑。代码简洁且易于理解,适用于处理具有环形结构的交换问题。掌握此类算法思维对编程竞赛中复杂路径问题的解决具有重要价值。

参考:2016蓝桥杯省赛B组交换瓶子题解

原创内容 转载请注明出处

分享给朋友:

相关文章

力扣第1991题:寻找数组的中心索引 如何找到左右和相等的中心索引

力扣第1991题:寻找数组的中心索引 如何找到左右和相等的中心索引

题目解读给定一个整数数组,我们需要找到一个中心索引,使得该索引左侧所有元素的和等于右侧所有元素的和。如果不存在这样的索引,则返回-1。中心索引的定义不包含在左右两侧的和计算中。这个问题考察对数组遍历和...

力扣35:二分法在搜索插入位置中的运用

力扣35:二分法在搜索插入位置中的运用

有序数组的定位在一个严格递增的数字序列中,每个元素都有其确定的位置。当新元素试图加入时,我们需要回答两个问题:它是否已经存在?如果不存在,它应该插入在哪里?这道题要求我们在O(log n)时间内完成这...

2024蓝桥杯省赛B组前缀总分(洛谷P12124)解题思路与代码详解

2024蓝桥杯省赛B组前缀总分(洛谷P12124)解题思路与代码详解

一、题目解读2024年蓝桥杯省B组题目“前缀总分”(对应洛谷P12124)要求计算给定字符串集合中,所有前缀的最长公共前缀(LCP)的总分,并找出通过移动字符位置后可能获得的最大总分。题目考察字符串处...

2024年GESP四级宝箱题(洛谷P4006)题解:滑动窗口算法优化最长子序列和

2024年GESP四级宝箱题(洛谷P4006)题解:滑动窗口算法优化最长子序列和

一、题目解读本题为2024年GESP四级中的“宝箱”问题(对应洛谷P4006),要求在一个由n个宝箱组成的序列中,找出一个连续子序列,使得该子序列中宝箱价值之和最大,且子序列中最大值与最小值的差不超过...

【洛谷1184题解析】用C++高效解决地点匹配问题(附代码与解题思路)

【洛谷1184题解析】用C++高效解决地点匹配问题(附代码与解题思路)

一、题目解读洛谷1184题要求处理一组地点列表与行程记录,统计其中匹配的天数。题目难点在于高效处理带有空格的字符串输入,以及快速判断每日行程是否在高手可去地点集合中。需要兼顾输入格式解析与算法效率。二...

洛谷1220题解:动态规划与区间DP优化解法(附代码注释)

洛谷1220题解:动态规划与区间DP优化解法(附代码注释)

一、题目解读洛谷1220题要求计算在n个位置放置灯的情况下,通过关闭连续区间灯并移动至区间端点,使得总耗电量最小。需考虑灯的功率与位置差异,设计高效的算法求解最优策略。二、解题思路1. 动态规划 +...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。