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

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

6个月前 (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组交换瓶子题解

原创内容 转载请注明出处

分享给朋友:

相关文章

力扣LCR182:字符串操作三连 从基础拼接到底层指针优化

力扣LCR182:字符串操作三连 从基础拼接到底层指针优化

题目重解需要将密码字符串从第target个字符开始进行重新排列,形成新的动态密码。例如输入"password"和target=3,结果应为"swordpas"。...

牛客DP41精讲:当背包必须装满时,你的状态转移方程该如何调整?

牛客DP41精讲:当背包必须装满时,你的状态转移方程该如何调整?

题目重解我们面对一个经典背包问题的变体:给定n个物品,每个物品有重量w和价值v,背包容量为V。需要回答两个问题:1) 普通情况下能获得的最大价值;2) 必须恰好装满背包时的最大价值(若无法装满则输出0...

力扣144:递归之美 轻松掌握二叉树前序遍历

力扣144:递归之美 轻松掌握二叉树前序遍历

题目解读二叉树的前序遍历是一种基础但重要的树遍历方式,其遍历顺序为:先访问根节点,然后递归地前序遍历左子树,最后递归地前序遍历右子树。给定一个二叉树的根节点,我们需要按照这个顺序访问所有节点,并将它们...

标题:洛谷B3617题解析:八进制转十六进制算法实现与优化(附AC100代码)

标题:洛谷B3617题解析:八进制转十六进制算法实现与优化(附AC100代码)

一、题目解读洛谷B3617题要求将输入的八进制字符串转换为十六进制表示。题目需处理大数场景,且对输入合法性有明确限制(长度不超过1000,仅包含0-7字符)。由于八进制与十六进制无法直接转换,需借助十...

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

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

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

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

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

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

发表评论

访客

看不清,换一张

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