关闭

Codeforces Round #369 (Div. 2) D. Directed Roads

标签: codeforcesdfs
75人阅读 评论(0) 收藏 举报
分类:

题目链接

题意:给你一个n个点,n条有向边的图,你可以使任意条边反向,但是每条边只能反向一次,请求出使图不存在环的所有方案数量

仔细思考我们发现,对于一个点数为x的环,除去全部不反向和全部反向两种情况,其他的所有方案总数为(2^x)-2种

对于不在环上的边,无论反向还是不反向对环的存在都是没有影响的,因此如果有y条边不在环上,就有2^y种情况

最后将所有的情况乘起来就可以了,环的存在需要dfs预处理一下

——————因为这里每个点的出度只有1,所有要成环肯定是沿着给定nxt找下去找得到。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define mod 1000000007
const int maxn=200005;
int nxt[maxn],vis[maxn],loop[maxn];
int n,tot;
void findloop(int x){
   loop[tot]=1;
   vis[x]=3;
   while(vis[nxt[x]]!=3){
    x=nxt[x];
    vis[x]=3;
    loop[tot]++;
   }
}
void dfs(int x){
    vis[x]=2;
    if(!vis[nxt[x]])dfs(nxt[x]);
    if(vis[nxt[x]]==2){
        tot++;
        findloop(nxt[x]);
    }
    //if(vis[nxt[x]]==1||vis[nxt[x]]==3)
        vis[x]=1;
}
LL quickpowmod(LL x,LL y,LL mo)
{
      LL ret = 1;
      while(y){
         if(y&1)
             ret = ret*x%mo;
         x = x*x%mo;
         y >>= 1;
     }
   return ret;
 }

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&nxt[i]);
    tot=0;
    for(int i=1;i<=n;i++){
        if(!vis[i])dfs(i);
    }
    LL ans=1;
    for(int i=1;i<=tot;i++){
        ans=ans*((quickpowmod(2,loop[i],mod)-2+mod)%mod)%mod;
        n-=loop[i];
    }
    ans=ans*quickpowmod(2,n,mod)%mod;
    cout<<ans<<endl;
    return 0;
}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:35059次
    • 积分:3043
    • 等级:
    • 排名:第11490名
    • 原创:282篇
    • 转载:2篇
    • 译文:0篇
    • 评论:1条
    文章分类