要求只能将0和其它元素交换,达到排序的目的。
将初始序列第i个元素和目标序列第i个元素视作有联系的,因为经过数次交换后目标序列第i个元素必将到第i个的位置上。这里用并查集做,最后求环的个数。
//初始序列
3 5 7 2 6 4 9 0 8 1
//目标序列
0 1 2 3 4 5 6 7 8 9
这里有三个环:0-3-2-7-0、5-4-6-9-1-5和8。这里8本来就在目标位置,所以不计入最后环的个数。
假设一个环内有k个元素。那么
- 对0所在的环排序时,排序次数为k-1
- 对0不在的环排序时,排序次数为k+1.(因为需要先把0和环内某个元素交换,再换回去,多了两次次数)
0最多只能在一个环里,也可能0本来就在0的位置上。所以
- 如果在待交换的元素中有0,那结果应该是集合数+待交换元素数-2
- 如果待交换元素中没有0,那结果应该是集合数+待交换元素数
所以
#include <bits/stdc++.h>
using namespace std;
int father[100010];
int findFather(int x){
int a=x;
while(father[x]!=x){
x=father[x];
}
while(a!=x){
int temp=father[a];
father[a]=x;
a=temp;
}
return x;
}
void Union(int a,int b){
int faa=findFather(a);
int fab=findFather(b);
father[faa]=fab;
}
int main(){
int arr[100010];
int n,cnt=0,id0=-1;
cin>>n;
vector<int> vec;
int have0=0;
for(int i=0;i<n;i++)father[i]=i;
for(int i=0;i<n;i++){
cin>>arr[i];
if(arr[i]!=i){
vec.push_back(i);
if(arr[i]==0)have0=-2;
}
Union(arr[i],i);
}
set<int> root;
for(int item:vec)root.insert(findFather(item));
printf("%d",root.size()+vec.size()+have0);
}
本文介绍了一种使用并查集数据结构解决特定序列排序问题的方法。通过将初始序列和目标序列进行对比,利用并查集找出元素间的关联,最终确定排序所需的交换次数。特别关注了0元素在排序过程中的特殊作用。
275

被折叠的 条评论
为什么被折叠?



