P3420 [POI2005]SKA-Piggy Banks 并查集

  

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

任务:

写一段程序包括:

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

输入样例#1: 复制

4
2
1
2
4


一开始在考虑 3->1<-2 这种情况并查集连起来却要打碎两个罐子 但是这种情况是不存在的。。。。
直接无脑并查集可以过
#include
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
//
#define inf 0x3f3f3f3f
const int N=1000000+5;
int f[N];
int find1(int x)
{
    return f[x]==x?x:f[x]=find1(f[x]);
}

bool cmp(node a,node b)
{
    return a.v>b.v;
}
void union1(int x,int y)
{
    int a=find1(x);
    int b=find1(y);
    if(a!=b)
        f[a]=b;
}
int main()
{
    int n;RI(n);
    rep(i,1,n)f[i]=i;
    rep(i,1,n)
    {
       int x;RI(x);
       union1(i,x);
    }
    int cnt=0;
    rep(i,1,n)
    if(f[i]==i)
        cnt++;
    cout<<cnt;
    return 0;
}
View Code

 








转载于:https://www.cnblogs.com/bxd123/p/10793047.html

你可能感兴趣的:(P3420 [POI2005]SKA-Piggy Banks 并查集)