tarjan强连通缩点——cf711D

模板题

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 500005
#define mod 1000000007
int n,a[N];
vector<int>G[N];
int cnt,dfn[N],low[N],ind,stk[N],ins[N],top;
vector<int>scc[N];
void tarjan(int x){
    dfn[x]=low[x]=++ind;
    stk[++top]=x,ins[x]=1;
    for(int i=0;i<G[x].size();i++){
        int y=G[x][i];
        if(!dfn[y]){
            tarjan(y);
            low[x]=min(low[x],low[y]);
        }
        else if(ins[y])
            low[x]=min(low[x],low[y]);
    }
    if(dfn[x]==low[x]){
        cnt++;int y;
        do{
            y=stk[top--];
            ins[y]=0;
            scc[cnt].push_back(y);
        }while(y!=x);
    } 
}
ll Pow(ll a,ll b){
    ll res=1;
    while(b){
        if(b%2)
            res=res*a%mod;
        b>>=1;a=a*a%mod;
    }
    return res;
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        G[i].push_back(a[i]);
    }
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            tarjan(i);
    
    ll ans=1;
    for(int i=1;i<=cnt;i++)
        if(scc[i].size()!=1)
            ans=ans*(Pow(2,scc[i].size())-2+mod)%mod;
        else ans=ans*2%mod;
    cout<<ans<<'
';
}
原文地址:https://www.cnblogs.com/zsben991126/p/11432798.html