Description
Byteazar 有 N 个小猪存钱罐. 每个存钱罐只能用钥匙打开或者砸开. Byteazar 已经把每个存钱罐的钥匙放到了某些存钱罐里. Byteazar 现在想买一台汽车于是要把所有的钱都取出来. 他想尽量少的打破存钱罐取出所有的钱,问最少要打破多少个存钱罐.
第一行一个整数 N (1 <= N <= 1.000.000) – 表示存钱罐的总数. 接下来每行一个整数,第 i+1行的整数代表第i个存钱罐的钥匙放置的存钱罐编号.
Solution
把限制关系看成是有向边然后求缩点后入度为0的连通块数量就是答案
然鹅这种方法并不能过内存限制(可能我的写法比较弱
随便换成并查集搞搞不就过了
Code
#include <stdio.h>
#include <string.h>
#include <stack>
#include <map>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define fill(x,t) memset(x,t,sizeof(x))
const int N=1000005;
int fa[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
int get_father(int x) {
if (!fa[x]) return x;
return fa[x]=get_father(fa[x]);
}
int main(void) {
int n=read();
rep(i,1,n) {
int x=get_father(read());
int y=get_father(i);
if (x==y) continue;
fa[y]=x;
}
int ans=0;
rep(i,1,n) ans+=(get_father(i)==i);
printf("%d\n", ans);
return 0;
}