zoukankan      html  css  js  c++  java
  • 小猪存钱罐

    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
    ",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 }
  • 相关阅读:
    easyui combobox 获取焦点
    easyui combobox keyhandler使用
    easyui combobox 取值
    Tomcat启动超时问题Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds
    spring定时器中如何获取servletcontext
    不用asp.net MVC,用WebForm照样能够实现MVC
    打印从1到最大的n位数
    [NOIP复习]第三章:动态规划
    Java并发与同步
    Bootstrap的js插件之按钮(button)
  • 原文地址:https://www.cnblogs.com/cutepota/p/12747761.html
Copyright © 2011-2022 走看看