清北学堂模拟赛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; }