给定数字串3 1 2 5 4,建立如下的有向图:
每个数字指向它应该在的位置的数,
直观的结果就是:
3 1 2 5 4
^ ^ ^ ^ ^
| | | | |
1 2 3 4 5
容易理解:得到的图必定是若干个(小于n)环组成的
情况1:如果交换同一个环内的任意2个数,再通过上述方法得到的便是3个环,及交换同一个环内的任意2个数,都会增加1个环。
情况2:如果交换2个不同环之间的任意2个数,再通过上述方法得到的便是这2个环合二为一
应用:有序的数字串的图是n个环,因为每交换1次,必定会增加1个环,假定现在有k个环,要想得到n个环,最少交换n-k次,所以只需要求出已有的环的数量即可。
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int N =10010;
int n;
int b[N];
bool st[N]; //判重数组
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>b[i];
int cnt=0;
for(int i=1;i<=n;i++){//遍历每一个数字,如果st【i】为false,说明该数字没有在任一环内,所以环数+1,然后将还数字能到达的所有数字的st都标记为true即可。
if(!st[i]){
cnt++;
for(int j=i;!st[j];j = b[j])
st[j]=true;
}
}
cout<<n-cnt;
return 0;
}