題目鏈接:傳送門
思路:自己的瞎搞的假算法得了8分。。(這裏就不貼了),然後看了題解,對於序列中的數字a[i],必定有數佔用了他原來的位置,存在一條佔用鏈:如:i 佔用 j的位置,j佔用k的位置,k佔用i的位置。(佔用鏈一定是一個環,應該可以證明)
具體思路就是:因爲只能用0交換,如果0不在自己的位置(則0佔據了別的數的位置),先通過交換使它在0位置(與它交換的全部的數字都會回到自己的位置),然後看第i個數,是否在自己的位置,如果不在,就把他和0進行交換(讓0佔據他的位置),然後在下一輪交換進行交換後,會到達合適位置。每輪交換次數是num+1,num是本輪正確排序的數字。(這應該能最小的交換次數)
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int a[maxn] , vis[maxn];
int main() {
int n;
ios::sync_with_stdio(0);
cin >> n;
int cnt = 0 , ans = 0;
for(int i = 0 ; i < n ; i++) {
cin >> a[i];
vis[a[i]] = i;
}
int i = 1;
while(i < n) {
while(vis[0] != 0) {
int t = vis[0];
//swap(a[vis[t]] , a[vis[0]]);
swap(vis[t] , vis[0]);
ans++;
}
if(vis[i] != i) {
ans++;
swap(vis[i] , vis[0]);
//swap(a[vis[i]] , a[vis[0]]);
}
i++;
}
cout << ans << "\n";
return 0;
}