小猪存钱罐
作者:互联网
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
sol:两种方法:1.强连通分量缩圈;2.并查集
方法一中样例用有向图表示为:
缩圈后有两个入度为0的点,所以答案为2.
缩圈写法:
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define N 1000005 4 int n,w,head[N],nxt[N],ans,size[N]; 5 int to[N],cnt,dfn[N],st[N],r,k[N]; 6 int low[N],tot,top,num[N]; 7 bool vis[N]; 8 using namespace std; 9 inline void read(int &x){ 10 int datta=0;char chchc=getchar();bool okoko=0; 11 while(chchc<'0'||chchc>'9'){if(chchc=='-')okoko=1;chchc=getchar();} 12 while(chchc>='0'&&chchc<='9'){datta=datta*10+chchc-'0';chchc=getchar();} 13 x=okoko?-datta:datta; 14 } 15 inline void link(int a,int b){to[++cnt]=b,nxt[cnt]=head[a],head[a]=cnt;} 16 inline void t(int x){ 17 dfn[x]=low[x]=++tot; 18 st[++top]=x;int ttt=top; 19 for(int i=head[x];i;i=nxt[i]){ 20 int u=to[i]; 21 if(!num[u]){ 22 if(!dfn[u])t(u); 23 low[x]=min(low[u],low[x]); 24 } 25 } 26 if(dfn[x]==low[x]){ 27 r++; 28 while(top>=ttt) 29 num[st[top--]]=r,size[r]++; 30 } 31 } 32 int main(){ 33 read(n); 34 for(int i=1;i<=n;i++) 35 read(w),link(w,i); 36 for(int i=1;i<=n;i++) 37 if(!dfn[i])t(i); 38 for(int i=1;i<=n;i++) 39 for(int j=head[i];j;j=nxt[j]) 40 if(num[to[j]]!=num[i])k[num[to[j]]]++; 41 for(int i=1;i<=r;i++) 42 if(!k[i])ans++; 43 printf("%d\n",ans); 44 return 0; 45 }
并查集写法:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int fa[1000001],n,ans; 4 bool flag[1000001]; 5 int get(int x){ 6 if(fa[x]!=x)fa[x]=get(fa[x]); 7 return fa[x]; 8 } 9 int main() { 10 scanf("%d",&n); 11 for(int i=1;i<=n;i++){ 12 fa[i]=i; 13 } 14 for(int i=1;i<=n;i++) 15 { 16 int x; 17 scanf("%d",&x); 18 //第x个box的KEY在第i个box里,将它们并成一个集合 19 int p=get(x),q=get(i); 20 if(p!=q) 21 { 22 fa[p]=q; 23 } 24 } 25 for(int i=1;i<=n;i++) 26 { 27 int x=get(i); 28 if(fa[i]==i) //统计有多少个集合,就有打开多少个box 29 { 30 ans++; 31 flag[x]=true; 32 } 33 } 34 printf("%d",ans); 35 return 0; 36 }
标签:小猪,缩圈,int,fa,bool,存钱罐,chchc 来源: https://www.cnblogs.com/cutepota/p/12747761.html