ARC114 B - Special Subsets(并查集)

题意:

在这里插入图片描述

解法:

根据题目要求,选择了i就必须选择a[i],
那么构造一条i->a[i]的边.

由于每个点都有出边,因此图一定会出现环,
为了保证题目中a!=b时,f[a]!=f[b],
因此对于每个基图连通块,
只能选择环的那一块,如图:

在这里插入图片描述

发现每个基图连通块只有一种选法后,
可以用并查集计算有多少个基图连通块.

假设有cnt个连通块,那么答案为2^cnt-1,1是为了减去空集.

code:

#include <bits/stdc++.h>
#define int long long
#define PI pair<int,int>
using namespace std;
const int maxm=2e6+5;
const int mod=998244353;
int pre[maxm];
int n;
int ffind(int x){
    
    
    return pre[x]==x?x:pre[x]=ffind(pre[x]);
}
void solve(){
    
    
    cin>>n;
    for(int i=1;i<=n;i++){
    
    
        pre[i]=i;
    }
    for(int i=1;i<=n;i++){
    
    
        int x;cin>>x;
        pre[ffind(x)]=ffind(i);//选了i就必须选a[i]
    }
    int ans=1;
    for(int i=1;i<=n;i++){
    
    
        if(pre[i]==i){
    
    
            ans=ans*2%mod;
        }
    }
    ans=(ans-1+mod)%mod;
    cout<<ans<<endl;
}
signed main(){
    
    
    ios::sync_with_stdio(0);
    solve();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44178736/article/details/115033156
今日推荐