题解:AT_abc436_e [ABC436E] Minimum Swap
shaotianyu · · 题解
::::info[第一问]
给出一个非有序的排列,如何用最少的交换次数使其有序?
举个例子,我们给出一个排列
| 位置 | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| 元素 | 3 | 2 | 4 | 1 | 6 | 5 |
对于元素
这个图告诉了我们什么信息?
位置
位置
位置
发现了什么吗?对于一个环
::::
::::info[第二问]
我们按照上面的建图方法建图,即对于所有
第一次的交换操作,可以选择任意一个环中的任意两个元素进行交换,设建图后有
虽然意义上是有向图,但是由于题目性质,这里可以当无向图来建。使用并查集来维护。
时间复杂度
::::success[代码]
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
using namespace std;
const int N=3e5+10;
int n,x,fa[N],siz[N];
long long ans;
int find(int x){return (x^fa[x])?fa[x]=find(fa[x]):fa[x];}
void merge(int u,int v){
int fu=find(u),fv=find(v);
if(fu!=fv) fa[fu]=fv,siz[fv]+=siz[fu];
}
int main(){
scanf("%d",&n);
rep(i,1,n) fa[i]=i,siz[i]=1;
rep(i,1,n) scanf("%d",&x),merge(x,i);
rep(i,1,n) if(fa[i]==i) ans+=1ll*(siz[i]-1)*siz[i]/2ll;
cout<<ans;
return 0;
}
::::