首先给的每个点只有一个出度既不可能有大于一个出度
每条边可以改变方向
所以每个点最多只能在一个环上,且所有有向环的信息已经给出因为每个点只有一个出度
dfs把每个环都求出来 ans *( 2^n(环的边数) - 2)
最后ans * 2^m(链的边数)
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<map>
#define maxn 200005
#define mod 1000000007ll
#define LL long long
#include<vector>
using namespace std;
vector<LL>ve[maxn];
int sym[maxn], sym2[maxn];
int siz[maxn];
LL n, ans = 1;
LL fastMod(LL n)
{
LL ans = 1, pre = 2;
while(n)
{
if(n & 1ll)ans *= pre;
pre *= pre;
pre %= mod;
ans %= mod;
n >>= 1ll;
}
return ans;
}
void dfs(LL pre, LL sum)
{
sym[pre] = 1;
sym2[pre] = 1;
siz[pre] = sum;
for(int i = 0; i < ve[pre].size(); i++)
{
if(sym[ve[pre][i]])
{
if(sym2[ve[pre][i]] == 1)
{
ans *= ((fastMod(siz[pre] - siz[ve[pre][i]] + 1) - 2) % mod + mod) % mod;
ans %= mod;
n -= siz[pre] - siz[ve[pre][i]] + 1;
}
}
else dfs(ve[pre][i], sum + 1);
}
sym2[pre] = 0;
}
int main()
{
scanf("%I64d", &n);
for(int i = 1; i <= n; i++)
{
LL pre;
scanf("%I64d", &pre);
ve[i].push_back(pre);
}
LL n1 = n;
for(int i = 1; i <= n1; i++)
if(!sym[i]) dfs(i, 1);
ans *= fastMod(n);
ans %= mod;
printf("%I64d\n", ans);
return 0;
}
本文介绍了一种针对特殊有向图结构的算法,该图中每个节点仅有一个出度。通过深度优先搜索(DFS)遍历每个环,并利用快速幂计算环与链的组合数量,最终得出所有可能的组合方式。
974

被折叠的 条评论
为什么被折叠?



