求一棵树的拓扑排序个数,公式简化为 f(n)=(sum(0)-1)!/(sum(1)*sum(2)*...*sum(n)),其中0是树根,sum(i)是i节点所在树的节点个数
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#define maxn 40010
#define maxm 1000
#define ll long long
#define sf scanf
#define pf printf
const ll mod=1000000007;
#define clr(x) memset(x,0,sizeof(x))
using namespace std;
int t,n,m;
ll ans;
vector<int> g[maxn+10];
int du[maxn+10];
ll sum[maxn+10],resum[maxn+10];
void init(){
for(int i=0;i<=maxn;i++) g[i].clear();
for(int i=0;i<=n;i++) sum[i]=1;
clr(du),clr(resum);
}
void dfs(int u){//求u节点及其子树的节点个数
for(int i=0;i<g[u].size();i++){
int v=g[u][i];
dfs(v);
sum[u]+=sum[v];
}
}
void exgcd(ll a,ll b,ll d,ll &x,ll &y){//求a*x+b*y=d 且|x|+|y|最小
if(!b){ d=a;x=1,y=0; }
else { exgcd(b,a%b,d,y,x); y-=x*(a/b); }
}
void cal(){
ans=1;
for(int i=1;i<=sum[0]-1;i++){//(sum[0]-1)!
ans=((ans%mod)*(i%mod))%mod;
}
for(int i=1;i<=n;i++){
ans=((ans%mod)*(resum[i]%mod))%mod;
}
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
init();
for(int i=0;i<m;i++){
int a,b;
scanf("%d%d",&a,&b);
g[b].push_back(a);
du[a]++;
}
for(int i=1;i<=n;i++){
if(!du[i]){
g[0].push_back(i);
}
}
dfs(0);
// printf("\n");
for(int i=1;i<=n;i++){
ll x=0,y=0,d=1;
exgcd(sum[i],mod,d,x,y);
resum[i]=(x+mod)%mod;
// printf("%lld ",resum[i]);
}
//printf("\n");
cal();
pf("%lld\n",ans);
}
}