P3420 [POI2005]SKA-Piggy Banks

题面

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

任务:

写一段程序包括:

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

思路

判断环,有环就砸。

做法

并查集,出来吧!

伪代码如下:

for i:1->n
begin
	if(Find(x)=i)
   begin
   	fa[i]=i
    ans++;
   end
   else
   begin
   	fa[i]=x
   end
end

实际代码如下

#include<bits/stdc++.h>
using namespace std;

// size:大小 compress:路径压缩 merge_rank:按秩合并 
template<int size=2500,bool compress=true,bool merge_rank=true>
class UnionFindSet{
    private:
        int fa[size+1];
        int rank[size+1];
    public:
        UnionFindSet(){
            for(int i=0;i<size;i++){
                this->fa[i]=i;
                if(merge_rank){
                    this->rank[i]=1;
                } 
            }
        }
        int find(int x){
            if(!compress){
                if(this->fa[x]==x){
                    return x;
                }
                else{
                    return this->find(this->fa[x]);
                }
            }
            else{
                if(x==this->fa[x]){
                    return x;
                }
                else{
                    this->fa[x]=this->find(this->fa[x]);
                    return fa[x];
                }
            }
        }
        void merge(int x,int y){
            if(!merge_rank){
                this->fa[this->find(x)]=find(y);
            }
            else{
                int a=this->find(x);
                int b=this->find(y);
                if(this->rank[a]<=this->rank[b]){
                    this->fa[a]=b;
                }
                else{
                    this->fa[b]=a;
                }
                if(rank[a]==rank[b]&&a!=b){
                    rank[b]++;
                }
            }
        }
        bool same(int x,int y){
            return this->find(x)==this->find(y);
        }
        void _fa_setValue(int i,int x){
            this->fa[i]=x;
        }
        int _fa_getValue(int i){
            return this->fa[i]; 
        }
        void _rank_setValue(int i,int x){
            this->rank[i]=x;
        }
        int _rank_getValue(int i){
            return this->rank[i];
        }
};

int n,ans=0;
UnionFindSet<1000005,true,true> uf;

int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		int x;
		cin>>x;
		if(uf.find(x)==i){
			uf._fa_setValue(i,i);
			ans++;
		}
		else{
			uf._fa_setValue(i,x);
		}
	}
	cout<<ans;
	return 0;
}
posted @ 2022-01-26 15:26  蒟蒻xiezheyuan  阅读(19)  评论(0编辑  收藏  举报