Good Bye 2022: 2023 is NEAR D

D. Koxia and Game

tilian
很容易发现就是我们要让每个数字都double choice一次才能得到答案
比如第一个样例
我们发现1 1 已经double choice一次过了 所以我们该点可以搞任何的数字就是n种选择
我们发现第二个和第三个就像一个环一样 确定了一个其他所有都被确定了就只有两种情况
而且我们会发现有些像链一样 (我们把a[i]和b[i]用边连起来)
1 2 3
2 3 4
这种是没有解的 但是他要是挂在一个环上的话就有解了
1 2 3 4
2 3 4 4
所以我们会发现一个连通块必须有几个点 就要有几条边
这样我们就记录一下 谁是自环 每个连通块有几个点几个边即可

int n,p[N],v[N],e[N],loop[N],a[N],b[N];
int find(int x){
    if(p[x]!=x)p[x]=find(p[x]);
    return p[x];
}
void merge(int x,int y){
    int pa=find(x),pb=find(y);
    e[pa]+=e[pb];
    v[pa]+=v[pb];
    p[pb]=p[pa];
    loop[pa]|=loop[pb];
}
void solve(){
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=n;i++)cin>>b[i];
    for(int i=1;i<=n;i++){
        loop[i]=e[i]=0;
        p[i]=i;
        v[i]=1;
    }
    for(int i=1;i<=n;i++){
        int pa=find(a[i]),pb=find(b[i]);
        if(pa!=pb)merge(pa,pb);
        e[find(a[i])]++;
        if(a[i]==b[i])loop[pa]=1;
    }
    vector<int>mp(n+1);
    int ans=1;
    for(int i=1;i<=n;i++){
        int x=find(i);
        if(mp[x])continue;
        if(e[x]!=v[x])ans=0;
        if(loop[x])(ans*=n)%=mod;
        else (ans*=2)%=mod;
        mp[x]++;
    }
    cout<<ans<<endl;
}
posted @ 2022-12-31 16:46  ycllz  阅读(41)  评论(0)    收藏  举报