• CodeForces 711D Directed Roads (DFS找环+组合数)


    <题目链接>

    题目大意:

    给定一个$n$条边,$n$个点的图,每个点只有一条出边(初始状态),现在能够任意对图上的边进行翻转,问你能够使得该有向图不出先环的方案数有多少种。

    解题分析:

    很明显本题需要对环的部分和链的部分分开进行讨论,对于环的部分,能够使得该环不为有向环的方案数有$2^k-2$种($k$为环上的点数,相当于减去环上所有边都是顺时针和逆时针情况),对于链的部分,方案数就是$2^k$($k$为链上的点数)。因为初始状态每个点只有一条出边,所以即使存在环,也一定是简单环(即不存在环套环的情况),找环直接用DFS即可。

    #include <bits/stdc++.h>
    using namespace std;
    #define REP(i,s,t) for(int i=s;i<=t;i++)
    typedef long long ll;
    const int N = 2e5+5;
    const int mod = 1e9+7; 
    int n,tot,col;
    ll ans,cnt,dfn[N];
    int nxt[N],vis[N];
    
    ll pow(ll a,ll b){
        ll res=1;
        while(b){
            if(b&1)res=(res*a)%mod;
            a=(a*a)%mod;
            b/=2;
        }return res%mod;
    }
    void dfs(int u){
        vis[u]=col;
        dfn[u]=++tot;
        int v=nxt[u];
        if(!vis[v])dfs(v);
        else if(vis[v]==col){       //如果遇到相同标记的点,表示遇到了环    
            ll num = dfn[u]-dfn[v]+1;      
            ans = ans*(pow((ll)2,num)-2)%mod;
            cnt-=num;     //cnt表示链上节点的数量      
        }
    }
    int main(){
        scanf("%d",&n);
        REP(i,1,n)scanf("%d",&nxt[i]);
        ans=1;cnt=n; 
        REP(i,1,n) if(!vis[i]) {
            tot=0;++col;
            dfs(i);
        }
        ans = ans*(pow((ll)2,cnt))%mod;
        printf("%lld
    ",ans);
    }
  • 相关阅读:
    《人件》读书笔记3
    《人件》读书笔记2
    《人件》读书笔记1
    《编程珠玑》读书笔记3
    《编程珠玑》读书笔记2
    学习进度报告2021/4/10
    《编程珠玑》读书笔记1
    学习进度报告2021/4/9
    学习进度报告2021/4/8
    关于软件体系架构质量属性的科技小论文
  • 原文地址:https://www.cnblogs.com/00isok/p/10902326.html
Copyright © 2020-2023  润新知