交换(成环问题)

链接:https://ac.nowcoder.com/acm/contest/5773/E
来源:牛客网

牛客幼儿园的小朋友课间操时间需要按照学号从小到大排队,但是他们太小了只能站成一列顺序却不对,现在幼儿园的阿姨需要帮忙交换小朋友的位置让他们最终有序,阿姨希望能尽快完成交换操作,问最少需要交换多少次,才能使得小朋友们从小到大排好。
注意:每个小朋友的学号不同,但是未必连续,因为可能有小朋友请假了没有来。

输入描述:

第一行一个整数 N。
接下来 N 行每行一个整数,为小朋友们的队列。

输出描述:

一个整数表示小朋友们的最小交换次数。
示例1

输入

3
2
1
3

输出

1

备注:

N≤100000,其他整数均≤109N\leq100000,其他整数均\leq 10^{9}N100000109


思路:这题挺有意思的,因为线代学多了我一开始以为是逆序数。成一个环需要交换的次数就减一,因为此环中有一次交换可以让两个数恢复原位,不需要换和两个互换的也可以借助map看成环。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int mod=1e9+7;
const int N=1e5;
int a[N],b[N],flag[N];
int n;

int find_min(){
int num=0;
for(int i=0;i<n;i++) b[i]=a[i];
sort(b,b+n);
map<int,int>m;
for(int i=0;i<n;i++) m[b[i]]=i;
for(int i=0;i<n;i++){
    if(!flag[i]){
        int j=i;
        while(!flag[j]){
            flag[j]=true;
            j=m[a[j]];
        }
        num++;
    }
}
return n-num;
}

int main(){
   cin>>n;
   for(int i=0;i<n;i++)
    cin>>a[i];
   int ans=find_min();
   cout<<ans<<endl;
return 0;
}

猜你喜欢

转载自www.cnblogs.com/asunayi/p/12980446.html