bzoj 1529

【bzoj1529】[POI2005]ska Piggy banks

2014年5月17日 855 0

Description

Byteazar 有 N 个小猪存钱罐. 每个存钱罐只能用钥匙打开或者砸开. Byteazar 已经把每个存钱罐的钥匙放到了某些存钱罐里. Byteazar 现在想买一台汽车于是要把所有的钱都取出来. 他想尽量少的打破存钱罐取出所有的钱,问最少要打破多少个存钱罐.

Input

第一行一个整数 N (1 <= N <= 1.000.000) – 表示存钱罐的总数. 接下来每行一个整数,第 i+1行的整数代表第i个存钱罐的钥匙放置的存钱罐编号.

Output

一个整数表示最少打破多少个存钱罐.

Sample Input

4
2
1
2
4

Sample Output


2

In the foregoing example piggy banks 1 and 4 have to be smashed.


解题思路:原本想用tarjan来做,看到黄学长说超空间。又看到并查集的做法,神奇啊。。。

好像最小点基可以用并查集来求。


#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n;
int f[1000001];


inline int read()
{
char y; int x=0,f=1; y=getchar();
while (y<'0' || y>'9') {if (y=='-')f=-1; y=getchar();}
while (y>='0' && y<='9') {x=x*10+int(y)-48; y=getchar();}
return x*f;
}


int find(int o) 
{
if (f[o]!=o) f[o]=find(f[o]);
return f[o];
}


int main()
{
n=read();
for (int i=1;i<=n;++i)
f[i]=i;
for (int i=1;i<=n;++i)
{
int u=read();
int x1=find(u); int x2=find(i);
if (x1!=x2)
{
f[x1]=x2;
 }
}
int ans=0;
for (int i=1;i<=n;++i)
if (find(i)==i)
 ans+=1;
printf("%d",ans);
}

你可能感兴趣的:(bzoj 1529)