https://www.acwing.com/problem/content/description/1226/
暴力做法:
#include<iostream>
using namespace std;
const int N=10010;
int s[N];
int n,cnt;
int main()
{
cin>>n;
for(int i=1;i<=n;i++) scanf("%d",&s[i]);
for(int i=1;i<=n;i++) while(s[i]!=i) swap(s[i], s[s[i]]), cnt++;
cout<<cnt;
return 0;
}
正解:
让每一个点和其想要到达的位置连边,你会发现回形成若干个环。
对于每次操作,我们有两种情况:
- 交换同一个环的两点,结果是环会裂出来一个环。
- 交换不同环的两点,结果是环回合到并一块。
我们最终的结果一定是形成n个环,那么一定有方法可以将k个环变成n个环,最少的步骤就是 n-k
#include<iostream>
using namespace std;
const int N=10010;
int s[N];
int vis[N];
int n,cnt;
int main()
{
cin>>n;
for(int i=1;i<=n;i++) scanf("%d",&s[i]);
for(int i=1;i<=n;i++)
{
if(!vis[s[i]])
{
for(int j=s[i];!vis[j];j=s[j]) vis[j]=1;
cnt++;
}
}
cout<<n-cnt;
return 0;
}