题目链接
http://codeforces.com/contest/711/problem/D
思路
这道题的输入很神奇,由输入可以得出一个结论就是每个点最多只会有一条出边,因此每个点最多在一个环中。
然后对于一个环比如1 -> 2 -> 3 -> 1,其方案数是
23−2
,然后可以发现,对每一个独立的环,若有x个点,那么方案数就是
2x−2
对所有环,由输入得到的性质,因此结果直接相乘即可
代码
#include <iostream>
#include <cstring>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <deque>
#include <bitset>
#include <algorithm>
using namespace std;
#define PI acos(-1.0)
#define LL long long
#define PII pair<int, int>
#define PLL pair<LL, LL>
#define mp make_pair
#define IN freopen("in.txt", "r", stdin)
#define OUT freopen("out.txt", "wb", stdout)
#define scan(x) scanf("%d", &x)
#define scan2(x, y) scanf("%d%d", &x, &y)
#define scan3(x, y, z) scanf("%d%d%d", &x, &y, &z)
#define sqr(x) (x) * (x)
const int maxn = 2 * 100000 + 5;
const int mod = 1e9 + 7;
vector<int> G[maxn];
int n, scc_cnt, sccno[maxn], pre[maxn], lowlink[maxn], dfs_clock;
stack<int> S;
void dfs(int u) {
pre[u] = lowlink[u] = ++dfs_clock;
S.push(u);
for (int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if (!pre[v]) {
dfs(v);
lowlink[u] = min(lowlink[u], lowlink[v]);
} else if (!sccno[v]) {
lowlink[u] = min(lowlink[u], pre[v]);
}
}
if (lowlink[u] == pre[u]) {
scc_cnt++;
while (1) {
int x = S.top(); S.pop();
sccno[x] = scc_cnt;
if (x == u) break;
}
}
}
void find_scc() {
dfs_clock = scc_cnt = 0;
memset(sccno, 0, sizeof(sccno));
memset(pre, 0, sizeof(pre));
for (int i = 1; i <= n; i++) {
if (!sccno[i]) dfs(i);
}
}
LL power(int x) {
LL ans = 1;
for (int i = 1; i <= x; i++) (ans <<= 1) %= mod;
return ans - 2;
}
int main() {
scan(n);
for (int i = 1; i <= n; i++) {
int x;
scan(x);
G[i].push_back(x);
}
find_scc();
int cnt[maxn];
memset(cnt, 0, sizeof(cnt));
for (int i = 1; i <= n; i++) cnt[sccno[i]]++;
LL res = 1;
for (int i = 1; i <= n; i++) {
LL x = (LL)(cnt[i]);
if (!x) break;
if (x >= 2) ((res *= power(x))) %= mod;
else if (x == 1) (res *= 2) %= mod;
}
printf("%I64d\n", res);
return 0;
}