NKOJ全TJ计划——NP5681
题目描述
果老师有一个 \(1\) 到 \(n\) 的排列\(p_1,p_2,...,p_n\)。
果老师给了你个\(m\)数对,\((x_1,y_1),(x_2,y_2),...,(x_m,y_m)\)。
现在你可以选取任意对数\((x_i,y_i)\), 每个数对可以选取任意次, 然后使用选择的某对数进行操作,操作的方式为交换 \(p_{x_i}\) 和 \(p_{y_i}\) 的位置。
最终你想要\(p_i=i\)的位置尽量多。输出最多可以有多少个这样的位置。
分析
每输入一个数对,就用并查集给它们绑在一起,然后如果\(i\)和\(p_i\)被绑在一起,它们就一定可以通过把它们绑在一起的数对交换成如此状况。
代码(rhx:没有代码的TJ不是好TJ,不想给代码上TJ的作者不是好作者)
看前三问:你是为抄袭而来吗?你理解思路了吗?你需要代码吗?
#include<bits/stdc++.h>
using namespace std;
int n,m,a[100004],p[100004];
int i,j,b,c,ans=0;
int f(int a){
if(p[a]==a){
return a;
}
p[a]=f(p[a]);
return p[a];
}
int main()
{
cin>>n>>m;
for(i=1;i<=n;i++) p[i]=i;
for(i=1;i<=n;i++) cin>>a[i];
for(i=1;i<=m;i++){
cin>>b>>c;
p[f(b)]=f(c);
}
for(i=1;i<=n;i++){
if(f(i)==f(a[i])){
ans++;
}
}
cout<<ans;
}