E题 交换
题目:
给定一个包含1-n的数列,我们通过交换任意两个元素给数列重新排序
求最少需要多少次交换,能把数组排成按1-n递增的顺序,(数组中的元素互不重复)。
比如 初始状态 5 4 3 2 1 。交换5和1的位置 得到 1 4 3 2 5,再交换4 2的位置得到 1 2 3 4 5.只需要两次即可。
思路:
在原数组中,每个元素添加一个出边指向它最终的位置,这样画完出边后,
最少会成一个环,最多n个环。 然后原理就是, 最少交换次数=结点数n-形成的环数。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n;
vector<int> v;
bool vis[N];
int main() {
cin >> n;
for (int i = 0; i < n; ++i) {
int x;
cin >> x;
v.push_back(x);
}
vector<int> sortedv(v);
sort(sortedv.begin(), sortedv.end());
map<int, int> mp;
int len = sortedv.size();
for (int i = 0; i < len; ++i) mp[sortedv[i]] = i;
int loop = 0;
for (int i = 0; i < len; ++i) {
if (!vis[i]) {
int t = i;
while (!vis[t]) {
vis[t] = true;
t = mp[v[t]];
}
loop++;
}
}
cout << len - loop;
return 0;
}