bzoj1529 [POI2005]ska Piggy banks
Posted ccz181078
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1529 [POI2005]ska Piggy banks相关的知识,希望对你有一定的参考价值。
Description
Byteazar 有 N 个小猪存钱罐. 每个存钱罐只能用钥匙打开或者砸开. Byteazar 已经把每个存钱罐的钥匙放到了某些存钱罐里. Byteazar 现在想买一台汽车于是要把所有的钱都取出来. 他想尽量少的打破存钱罐取出所有的钱,问最少要打破多少个存钱罐.
Input
第一行一个整数 N (1 <= N <= 1.000.000) – 表示存钱罐的总数. 接下来每行一个整数,第 i+1行的整数代表第i个存钱罐的钥匙放置的存钱罐编号.
Output
一个整数表示最少打破多少个存钱罐.
由存钱罐向钥匙所在存钱罐连边得到基环内向森林
从a能到达b说明若打破b可以打开a
因此答案为环的个数,拓扑排序求一下即可
#include<cstdio> char buf[10000005],*ptr=buf-1; inline int input(){ int x=0,c=*++ptr; while(c>57||c<48)c=*++ptr; while(c>47&&c<58)x=x*10+c-48,c=*++ptr; return x; } const int N=1000100; int n; int fa[N],q[N],in[N],ql=0,qr=0; bool ed[N]; int main(){ fread(buf,1,10000000,stdin); n=input(); for(int i=1;i<=n;i++)++in[fa[i]=input()]; for(int i=1;i<=n;i++)if(!in[i])q[qr++]=i; while(ql!=qr){ int w=q[ql++]; ed[w]=1; if(!--in[fa[w]])q[qr++]=fa[w]; } int ans=0; for(int a=1;a<=n;a++)if(!ed[a]){ int b=a; do{ b=fa[b]; ed[b]=1; }while(b!=a); ++ans; } printf("%d\n",ans); return 0; }
以上是关于bzoj1529 [POI2005]ska Piggy banks的主要内容,如果未能解决你的问题,请参考以下文章
Bzoj1529/POI2005 ska Piggy banks
BZOJ1529 [POI2005]ska Piggy banks
BZOJ 1529 [POI2005]ska Piggy banks(并查集)