算法:并查集
难度:水题(NOIP----)
这真的是一道水题,大佬们刷线段树、主席树累了,可以来写这道题。
很容易发现应该用并查集,同时,也易证 它具有传递关系,打开这个罐子,就能打开另某一个罐子
赋初值 ans=n;
所以,对于每一次merge,如果findf(x)!=findf(y),那么就说明ans可以减1了,
然后,,就,结束了。
代码如下
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#define N 1000005
using namespace std;
int fa[N];
int findf(int x)
{
if(x==fa[x]) return x;
return fa[x]=findf(fa[x]);
}
int ans;
void merg(int x,int y)
{
int t1=findf(x);
int t2=findf(y);
if(t1==t2) return ;
fa[t2]=t1;
ans--;
}
int main()
{
int n;
scanf("%d",&n);
ans=n;
for(int i = 1;i <= n;i++)
{
fa[i]=i;
}
for(int i = 1;i <= n;i++)
{
int f;
scanf("%d",&f);
merg(f,i);
}
printf("%d\n",ans);
return 0;
}