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

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

3天前

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组交换瓶子题解

原创内容 转载请注明出处

分享给朋友:

相关文章

70.爬楼梯|三步破解动态规划核心奥秘

70.爬楼梯|三步破解动态规划核心奥秘

题意新解:站在楼梯底仰望n级台阶,每步可选1或2阶,最终的路径组合犹如斐波那契数列般展开。比如到达第3阶的路径可由第1阶跨两步,或第2阶跨一步构成,这种递推规律揭示了两两相邻状态间的紧密关联。思路解析...

力扣第71题:用栈轻松解决Unix路径简化问题

力扣第71题:用栈轻松解决Unix路径简化问题

题目解读:在Unix风格的文件系统中,我们经常需要处理各种复杂的路径表示。给定一个绝对路径字符串,我们需要将其转换为最简化的规范路径。规范路径要求:路径始终以斜杠'/'开头;两个目录名...

IOI 1994 洛谷1216:如何用动态规划高效解决数字三角形问题?附完整代码解析

IOI 1994 洛谷1216:如何用动态规划高效解决数字三角形问题?附完整代码解析

题目重解给定一个由数字组成的三角形结构,从顶部出发,每次可以移动到下方相邻的数字,最终到达底部。我们的目标是找到一条路径,使得路径上经过的数字总和最大。这个问题在实际中有许多应用场景,如最优路径规划、...

【动态规划入门】力扣509题:斐波那契数列的经典解法与优化思路

【动态规划入门】力扣509题:斐波那契数列的经典解法与优化思路

题目解读‌斐波那契数列是一个经典的数学问题,在计算机科学中常被用作算法教学的入门案例。这个神奇的数列从0和1开始,后续每个数字都是前两个数字之和。题目要求我们计算第n个斐波那契数,看似简单的问题背后却...

洛谷1111题解题全解析:基于Kruskal算法与并查集的最小生成树实现

洛谷1111题解题全解析:基于Kruskal算法与并查集的最小生成树实现

一、题目解读洛谷1111题是一道经典的图论问题,要求构建一个无向图的最小生成树,并输出其最大边权值。题目核心在于通过给定的边集合,找到连接所有节点的最小权值子集,同时保证无环。这通常涉及最小生成树算法...

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

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

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

发表评论

访客

看不清,换一张

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