cf-div2-842d
题目链接:https://codeforces.com/problemset/problem/1768/D
知识:置换环,并查集
并且可以发现一个结论(可以自己画几个环图感受一下):
交换环内两个元素的位置,会将大环拆成小环。
交换两个环的两个元素的的位置,会将小环变成大环。
思路:最终要达成的序列为单元排列并且其中的两个数字交换位置。我们可以将num[i]和i连一条边。然后并查集维护环,如果存在一个环,它其中的环内元素有两个相邻数字时,那么答案需要减一,否则答案需要加一。
答案为将所有环拆成只有一个数字构成的环所需要的操作数。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
int num[N];
int p[N],sz[N];
set<int>S;
int find(int x){
if (x!=p[x]) p[x] = find(p[x]);
return p[x];
}
void solve(){
int n;
cin>>n;
S.clear();
for (int i=1;i<=n;i++) cin>>num[i];
for (int i=1;i<=n;i++) p[i] = i,sz[i] = 1;
for (int i=1;i<=n;i++){
int x = find(num[i]);
int y = find(i);
if (x!=y){
sz[y] += sz[x];
p[x] = y;
}
}
int flag = 1;
for (int i=1;i<=n;i++){
int x = find(i);
S.insert(x);
if (i<n){
if (find(i)==find(i+1)) flag = -1;
}
}
int ans = 0;
for (auto s:S){
if (sz[s]) ans += (sz[s]-1);
}
cout<<ans+flag<<'\n';
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int T;
T = 1;
cin>>T;
while(T--) solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端