Skip to content

Instantly share code, notes, and snippets.

@latte0119
Created August 16, 2016 07:58
Show Gist options
  • Save latte0119/f427bb68c9f6a1125b73220f766c7f7f to your computer and use it in GitHub Desktop.
Save latte0119/f427bb68c9f6a1125b73220f766c7f7f to your computer and use it in GitHub Desktop.
#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef vector<int>vint;
typedef pair<int,int>pint;
typedef vector<pint>vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define all(v) (v).begin(),(v).end()
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define pb push_back
#define fi first
#define se second
template<typename A,typename B>inline void chmin(A &a,B b){if(a>b)a=b;}
template<typename A,typename B>inline void chmax(A &a,B b){if(a<b)a=b;}
namespace SCC{
void visit(const vector<vector<int>>&G,vector<int>&vs,vector<int>&used,int v){
used[v]=true;
for(auto u:G[v]){
if(!used[u])visit(G,vs,used,u);
}
vs.push_back(v);
}
void visit2(const vector<vector<int>>&T,vector<int>&used,vector<int>&comp,vector<int>&vec,int k,int v){
comp[v]=k;
used[v]=true;
vec.push_back(v);
for(auto u:T[v]){
if(!used[u])visit2(T,used,comp,vec,k,u);
}
}
//G:強連結成分分解したいグラフ
//H:強連結成分を潰して1つの頂点に縮約したグラフ
//comp:Gの各頂点が、どのHの頂点に属しているか
void decompose(const vector<vector<int>>&G,vector<vector<int>>&H,vector<int>&comp){
vector<vector<int>>T(G.size());
for(int i=0;i<G.size();i++){
for(auto v:G[i]){
T[v].push_back(i);
}
}
comp.resize(G.size());
vector<int>vs(G.size());
vector<int>used(G.size());
for(int i=0;i<G.size();i++){
if(!used[i])visit(G,vs,used,i);
}
reverse(vs.begin(),vs.end());
fill(used.begin(),used.end(),0);
int K=0;
vector<vector<int>>S;
for(auto v:vs){
if(!used[v]){
S.push_back(vector<int>());
visit2(T,used,comp,S.back(),K++,v);
}
}
H.resize(K);
fill(used.begin(),used.end(),0);
for(int i=0;i<K;i++){
for(auto v:S[i]){
for(auto u:G[v]){
if(used[comp[u]]||comp[v]==comp[u])continue;
used[comp[u]]=true;
H[comp[v]].push_back(comp[u]);
}
}
for(auto v:H[i])used[v]=true;
}
}
}
int N,M;
vector<vector<int>>H;
const int mod=1000000007;
int dp[1000];
void dfs(int v){
dp[v]=1;
for(auto u:H[v]){
dfs(u);
dp[v]=dp[v]*(dp[u]+1)%mod;
}
}
signed main(){
scanf("%lld%lld",&N,&M);
vector<vector<int>>G(N);
rep(i,M){
int a,b;
scanf("%lld%lld",&a,&b);
a--;b--;
G[b].push_back(a);
}
vector<int>comp;
SCC::decompose(G,H,comp);
int ans=1;
int deg[1000]={};
rep(i,H.size())for(auto v:H[i])deg[v]++;
rep(i,H.size()){
if(deg[i]==0){
dfs(i);
ans=ans*(dp[i]+1)%mod;
}
}
cout<<ans<<endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment