题意:
给一张联通的有向图和点 S S S,问图中以 S S S为起点的欧拉回路数 n u m ( s ) num(s) num(s)。
BEST定理: 一 张 图 的 欧 拉 回 路 个 数 = d e t s ( K ) × ∏ v ∈ G ( d e g ( v ) − 1 ) ! 一张图的欧拉回路个数=det_s(K)\times \prod_{v\in G}{(deg(v)-1)!} 一张图的欧拉回路个数=dets(K)×∏v∈G(deg(v)−1)!
其中
K
K
K是基尔霍夫矩阵,
d
e
g
(
v
)
deg(v)
deg(v)表示
v
v
v的度数,
d
e
t
s
(
K
)
det_s(K)
dets(K)表示K抽去
s
s
s这一行一列后的主子式。(这里抽去任何一行一列似乎都可以,不过还是选择抽去题目给的起点)
然后如果边的环同构不算一种方案,还需要乘起点的度数。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e9+7;
const int maxn=1e5+5;
inline int read(){
char c=getchar();int t=0,f=1;
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){t=(t<<3)+(t<<1)+(c^48);c=getchar();}
return t*f;
}
int n,m;
int ans=0;
int ru[305],chu[305],mp[305][305],rec[maxn];
inline int am(int x){
return x>=mod?x-mod:x;
}
inline int ksm(int a,int b){
int ans=1;
while(b){
if(b&1)ans=1ll*ans*a%mod;
a=1ll*a*a%mod;b>>=1;
}
return ans;
}
int gauss(){
int ans=1,i,j;
for(i=2;i<=n;i++){//注意这里从2开始,说明删掉了第1行,第1列
for(j=i;j<=n;j++){
if(mp[j][i])break;
}
if(j!=i){
ans=mod-ans;
for(int k=i;k<n;k++)swap(mp[i][k],mp[j][k]);
}
ans=am((1ll*ans*mp[i][i])%mod+mod);
for(j=i+1;j<=n;j++){
if(mp[j][i]){
int st=am(1ll*mp[j][i]*ksm(mp[i][i],mod-2)%mod+mod);
for(int k=i;k<=n;k++){
mp[j][k]=am(mp[j][k]-1ll*st*mp[i][k]%mod+mod);
}
}
}
}
return ans;
}
signed main(){
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
n=read(),m=read();
for(int i=1;i<=m;i++){
int a=read(),b=read();
ru[b]++;chu[a]++;
mp[a][b]--;
mp[b][b]++;
}
/*for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)printf("%d ",mp[i][j]);
puts("");
}*/
for(int i=1;i<=n;i++){
if(ru[i]!=chu[i]){puts("0");return 0;}
}
if(n==1&&m==0){
puts("1");return 0;
}
rec[0]=1;
for(int i=1;i<=m;i++)rec[i]=1ll*rec[i-1]*i%mod;
ans=gauss();
//printf("%d\n",ans);
for(int i=1;i<=n;i++){
ans=1ll*ans*rec[chu[i]-1]%mod;
}
printf("%lld\n",1ll*ans*chu[1]%mod);
return 0;
}