清北学堂模拟赛d5t4 套路

分析:题目非常短,看起来非常难,其实把图一画就明白了.有向图,每个点的出度都是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;
}

 

posted @ 2017-10-11 15:27  zbtrs  阅读(373)  评论(0编辑  收藏  举报