码迷,mamicode.com
首页 > 其他好文 > 详细

CF711D 【Directed Roads】

时间:2019-10-05 22:49:38      阅读:111      评论:0      收藏:0      [点我收藏+]

标签:int   的区别   ace   col   -o   cte   name   etc   预处理   

这是一场比赛的 T4T4 ,身为蒟蒻的我当然没有想出来。

后来对基环树有了一点了解之后就来肝这道题。

首先对于一条边,只有两种情况

1.在环上,那么这个环只有全部正向或全部反向才可以成立,而总方案数显然是 2m ,其中 mm 是环上的边数,所以方案数就是 2m-2

2.不在环上,那么这种边就可以随意取,也就是2wm ,也就是所有的边数减去在环上的边。

先用拓扑排序找出所有的环,再用乘法原理统计就是了

注意的点

1.int 和bool的区别

2.ans初始化为1

3.拓扑排序注意记录深度
#include<bits/stdc++.h>
#define isdigit(a) (a>=48&&a<=57)
const int N=2e5+5;
const int mod=1e9+7;
using namespace std;
int n,a,head[N],tot;
struct node{int to,next;}e[N];
void add(int u,int v){e[++tot].to=v;e[tot].next=head[u];head[u]=tot;}

inline int read(){
    char c=getchar();int fh=0;
    while(!isdigit(c))c=getchar();
    while(isdigit(c))fh=(fh<<1)+(fh<<3)+(c^48),c=getchar();
    return fh;
}

int hh,m,po[N]={1},ans=1;
int vis[N],dfn[N];
void dfs(int u,int d){
    dfn[u]=d;vis[u]=1;
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].to;
        if(!vis[v])dfs(v,d+1);//还没访问过继续
        else if(vis[v]==1)hh=dfn[u]-dfn[v]+1,ans=(1ll*ans*(po[hh]-2+mod))%mod,m-=hh;//统计环上的边数,更新答案,边数减去在环上的边
    }
    vis[u]=2;//已访问过,且已经全部访问完
}
int main(){
    m=n=read();
    for(int i=1;i<=n;++i)po[i]=(po[i-1]*2ll)%mod;//预处理2的次幂
    for(int i=1;i<=n;i++)a=read(),add(i,a);//添加单向边
    for(int i=1;i<=n;++i)
     if(!vis[i]){
        hh=0;
        dfs(i,0);//拓扑排序
     }
    ans=(1ll*ans*po[m])%mod;//统计不是环上的边
    cout<<ans<<endl;
}

 




CF711D 【Directed Roads】

标签:int   的区别   ace   col   -o   cte   name   etc   预处理   

原文地址:https://www.cnblogs.com/coder-cjh/p/11625899.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!