清北学堂模拟赛d5t4 套路

本文介绍了一种解决特定有向图问题的方法,通过分析每个节点的出度为1的特点,利用乘法原理计算图中所有可能的边反转方案总数,并排除形成同向边的情况以得出最终答案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分析:题目非常短,看起来非常难,其实把图一画就明白了.有向图,每个点的出度都是1,那么整个图肯定是环上套链,链上的边无论怎样反向都不会形成环,环上的边也可以随便反向,但是最终不能反为同向的,总方案数减去反成同向的就是答案了.总方案数可以用乘法原理求出来.

#include <bits/stdc++.h>

using namespace std;

const int maxn = 100010,mod = 1e9+7;
int du[maxn],to[maxn],vis[maxn];
int n,cnt;
long long ans,qpow[maxn];

int main()
{
    freopen("road.in","r",stdin);
    freopen("road.out","w",stdout);
    queue <int> q;
    scanf("%d",&n);
    qpow[0] = 1;
    for (int i = 1; i <= n; i++)
        qpow[i] = (qpow[i - 1] * 2) % mod;
    for (int i = 1; i <= n; i++)
    {
        scanf("%d",&to[i]);
        du[to[i]]++;
    }
    for (int i = 1; i <= n; i++)
        if (!du[i])
    {
        q.push(i);
        cnt++;
    }
    while (!q.empty())
    {
        int u = q.front();
        vis[u] = 1;
        q.pop();
        du[to[u]]--;
        if (du[to[u]] == 0)
        {
            cnt++;
            q.push(to[u]);
        }
    }
    ans = qpow[cnt];
    for(int i = 1; i <= n; i++)
        if (!vis[i])
    {
        cnt = 0;
        int x = i;
        while (!vis[x])
        {
            cnt++;
            vis[x] = 1;
            x = to[x];
        }
        ans = (ans * (qpow[cnt] - 2 + mod)) % mod;
    }
    printf("%lld\n",ans);

    return 0;
}

 

转载于:https://www.cnblogs.com/zbtrs/p/7650820.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值