PAT_A1067
PAT甲级1067.
目录
A1067
题目
样例
输入:
10
3 5 7 2 6 4 9 0 8 1
输出:
9
思路和坑点
表排序。给出的序列,由若干个环组成。由于和0交换,因此根据环的特征分三类:
- 单独一个元素构成一个环,即自己在自己的位置上,不需要交换,交换次数为0
- 包含0的环,这样的环只和0交换,假设环中有n个元素,则需要交换n-1次
- 不包含0的换,由于只能和0交换,因此将任意一个环中的元素和0交换,将其纳入环中再进行交换,假设环中有n个元素,则需要n+1次交换
具体的解释参见代码注释或者参考MOOC陈越姥姥的讲解swap(0,*)
AC代码
#include<bits/stdc++.h>
using namespace std;
int main(void){
#ifdef ONLINE_JUDGE
#else
freopen("1.txt","r",stdin);
#endif
int n,ans=0;
cin>>n;
vector<int> v(n); //存储数据
vector<bool> vis(n,false); //访问标记
for(int i=0;i<n;i++){ //读取输入
cin>>v[i];
}
for(int i=0;i<n;i++){ //遍历数组,统计环,并计算
if(vis[i]==false){
int flag=0,cnt=0,k=i; //flag表示有没有0,如果是0表示没有,否则表示有,cnt统计环中元素个数
while(vis[k]==false){ //使用k做指针,遍历环并标记环上的元素为已访问
if(v[k]==0) flag=1;
vis[k]=true; cnt++; //统计环上元素个数
k=v[k];
}
if(cnt>1){ //如果环中的个数超过1
if(flag) ans+=cnt-1; //如果有0,则需要和0交换cnt-1 次
else ans+=cnt+1; //如果没有0,需要先把0任意交换进环中,然后此时共cnt+1个数,需要交换cnt+1-1=cnt次
//加上交换进去0的一次共cnt+1次
}
}
}
cout<<ans;
return 0;
}