zoukankan      html  css  js  c++  java
  • P3420 [POI2005]SKA-Piggy Banks

    题目描述

    Byteazar the Dragon拥有N个小猪存钱罐。每一个存钱罐能够用相应的钥匙打开或者被砸开。Byteazar已经将钥匙放入到一些存钱罐中。现在已知每个钥匙所在的存钱罐,Byteazar想要买一辆小汽车,而且需要打开所有的存钱罐。然而,他想要破坏尽量少的存钱罐,帮助Byteazar去决策最少要破坏多少存钱罐。

    任务:

    写一段程序包括:

    读入存钱罐的数量以及相应的钥匙的位置,求出能打开所有存钱罐的情况下,需要破坏的存钱罐的最少数量并将其输出。

    输入格式

    第一行:包括一个整数N(1<=N<=1000000),这是Byteazar the Dragon拥有的存钱罐的数量。

    存钱罐(包括它们对应的钥匙)从1到N编号。

    接下来有N行:第i+1行包括一个整数x,表示第i个存钱罐对应的钥匙放置在了第x个存钱罐中。

    输出格式

    仅一行:包括一个整数,表示能打开所有存钱罐的情况下,需要破坏的存钱罐的最少数量。

     这道题是并查集的较为简单的应用。如果第i个存钱罐的钥匙存储在了第j个存钱罐内,则打开了第j个存钱罐,也就间接地打开了第i个存钱罐。因此,如果第i个存钱罐的钥匙存储在了第j个存钱罐内,则我们一定可以通过打开第j个存钱罐的方式,拿到第i个存钱罐的钥匙。这样,我们可以将其理解为i和j被放到了一个集合里。这样我们只需要统计一共有几个集合,即可求出需要破坏的存钱罐数量。

    如何统计一共有几个集合?只需要在对father数组初始化时将集合数设为n,然后每进行一次合并操作将集合数减一即可。

    代码:

     1 #include<iostream>
     2 using namespace std;
     3 int n,x,y;
     4 int fa[1000005];
     5 inline int find(const int &x){
     6     if(fa[x]==x){
     7         return x;
     8     }else{
     9         return fa[x]=find(fa[x]);
    10     }
    11 }
    12 inline void unionn(const int &x,const int &y){
    13     int r1=find(x);
    14     int r2=find(y);
    15     fa[r1]=r2;
    16 }
    17 int main(){
    18     cin>>n;
    19     int num=n;//n个集合
    20     for(int i=1;i<=n;i++){
    21         fa[i]=i;
    22     }
    23     for(int i=1;i<=n;i++){
    24         cin>>x;
    25         if(find(i)!=find(x)){
    26             unionn(i,x);
    27             num--;
    28         }
    29     }
    30     cout<<num<<endl;
    31     return 0;
    32 }
  • 相关阅读:
    CodeForces
    4.15随笔
    oracle新建用户并赋予权限等
    catch时,获取异常信息
    ORACLE 判断是否为数字类型
    UNION ALL用法
    2019.11.7随笔
    oracle 查询锁表和解锁
    2019.11.1随笔
    oracle拼接子查询返回的多个结果
  • 原文地址:https://www.cnblogs.com/qianr/p/13380884.html
Copyright © 2011-2022 走看看