[CF 711D]Directed Roads
转载请注明出处:http://danihao123.is-programmer.com/
这个题啊……其实不难。
首先你注意,他告诉你你可以把边弄反。
其次注意,这个图不一定就有一个环。
然后每个环的取反法有[tex]2^x[/tex]种(假设环中有[tex]x[/tex]条边),但是空集不行,全集也不行,因此每个环爆掉的方案有[tex]2^x-2[/tex]种。然后环之外的边随便弄,乘法原理乱搞即可。
然后你是不是感觉这个题似曾相识?是的似乎这个题就是NOIP D1T2的翻版。
代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int maxn=200001; const ll MOD=1000000007; int G[maxn]; int in[maxn]; bool vis[maxn]; int n; inline bool jianz(){ register int i; bool ans=false; for(i=1;i<=n;i++){ if(!vis[i] && !in[i]){ ans=true; in[G[i]]--; vis[i]=true; G[i]=0; } } return ans; } ll dfs(int x,int y){ if(x==y && vis[x]){ return 0; }else{ vis[x]=true; return dfs(G[x],y)+1; } } ll pow_mod(ll a,ll b){ if(!b){ return 1; }else{ ll ans=pow_mod(a,b/2); ans=ans*ans%MOD; if(1&b){ ans=(ans*(a%MOD))%MOD; } return ans; } } inline ll solve(){ register int i; register ll Huan,temp=0,ans=1; while(jianz()); for(i=1;i<=n;i++) if(!vis[i]){ Huan=dfs(i,i); temp+=Huan; ans=(ans*(pow_mod(2,Huan)+MOD-2))%MOD; } ans=(ans*pow_mod(2,n-temp))%MOD; return ans; } int main(){ register int i; scanf("%d",&n); for(i=1;i<=n;i++){ scanf("%d",&G[i]); in[G[i]]++; } printf("%I64d\n",solve()); return 0; }