Given any permutation of the numbers {0, 1, 2,…, N−1}, it is easy to sort them in increasing order. But what if Swap(0, *) is the ONLY operation that is allowed to use? For example, to sort {4, 0, 2, 1, 3} we may apply the swap operations in the following way:
Swap(0, 1) => {4, 1, 2, 0, 3}
Swap(0, 3) => {4, 1, 2, 3, 0}
Swap(0, 4) => {0, 1, 2, 3, 4}
Now you are asked to find the minimum number of swaps need to sort the given permutation of the first N nonnegative integers.
Input Specification:
Each input file contains one test case, which gives a positive N (≤10
5
) followed by a permutation sequence of {0, 1, …, N−1}. All the numbers in a line are separated by a space.
Output Specification:
For each case, simply print in a line the minimum number of swaps need to sort the given permutation.
Sample Input:
10
3 5 7 2 6 4 9 0 8 1
Sample Output:
9
先给代码,后面在看我代码思路
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int a[N];
int main()
{
int n,t,cnt = 0;
cin >> n;
for (int i = 0; i < n; i ++ ){
cin >> t;
a[t] = i;
}
for (int i = 0; i < n; i ++ ){
while(a[0] != 0){
swap(a[a[0]],a[0]);
cnt ++ ;
}
if(a[i] != i){
swap(a[0],a[i]);
cnt ++;
}
}
cout<<cnt<<endl;
return 0;
}
思路分析:先说下我对题目的感觉吧,本题的思维性还是非常巧妙的,可能大部分同学都看了别的博客了,知道是用了贪心思想解,但感觉这些博客都没说到点子上,因为贪心的话其实是个正常人都能看出来,只要每次swap的位置都能让一个数到它本来的位置(比如6 到a[6] = 6)就能到最小步数,但是只依靠这个信息来解题是远远不够的。首先,你需要意识到这是个图论环的问题,如果你意识不到,那么本题就非常难了,还是举个栗子来说,比如题目里面的 {4, 0, 2, 1, 3},如果你画在图上,会发现是这样的环,然后按题目要求我们一个变成下面那样,每一个数都是自环。
从图里面可以发现,只要我们用0交换环里面一个数,那就会分裂出一个自环的数,这就是为什么代码里面要这样。
while(a[0] != 0){
swap(a[a[0]],a[0]);
cnt ++ ;
}
但是我们还要考虑一种情况,就是0自己是自环的情况,比如{0,3,4,1,2}
那在这个时候,我们就需要把0插入别的环,而且每插入一次步数都会+1,这个才能解释这段代码了,但是这样代码只是把0插入环而已,并没有把环的数和0连起来,但是没关系,因为在一个for循环里面,只要0不在自环,就肯定会遇到下一个结点把环和0连起来。
if(a[i] != i){
swap(a[0],a[i]);
cnt ++;
}
总得来说,本题思维还是很有跳跃性的,不要以为只是个25分的题目就轻视,更不是网上别人说的简单贪心,码字不易,有帮助的话给个赞吧。