傳送門
md這題和矩陣樹定理沒半毛錢關系qwq
首先先不考慮有環,一個\(DAG\)個外向樹個數為\(\prod_{i=2}^{n}idg_i(\)就是\(indegree_i)\),因為外向樹每個點入度為一,對于一個點有入度個父親可選,然后乘法原理起來就是答案
現在可能加一條邊會有環,那么答案可以考慮總方案減不合法方案,不合法的有環方案就是環內的點連好了,然后剩下的點貢獻方案,設\(s\)是個環,那么方案為\(\sum_{s}\prod_{i\notin s}idg_i=\sum_{s}\frac{\prod_{i=2}^{n}idg_i}{\prod_{i\in s}idg_i}=\prod_{i=2}^{n}idg_i\sum_{s}\frac{1}{\prod_{i\in s}idg_i}\)
后面那個東西,因為加了邊\(x\rightarrow y\),所以一條\(y\)到\(x\)可以確定一個環,那么以\(y\)為初始狀態,可拓撲排序一遍dp出來方案
注意\(y=1\)的情況
#include<bits/stdc++.h>
#define LL long long
#define db double
#define il inline
#define re registerusing namespace std;
const int N=1e5+10,mod=1e9+7;
il int rd()
{int x=0,w=1;char ch=0;while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}return x*w;
}
int to[N<<1],nt[N<<1],hd[N],dg[N],idg[N],tot;
void add(int x,int y){++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot,++dg[y];}
int n,m,u,v,f[N],inv[N];
queue<int> q;int main()
{n=rd(),m=rd(),u=rd(),v=rd();for(int i=1;i<=m;++i){int x=rd(),y=rd();add(x,y);}int ans=1;for(int i=2;i<=n;++i) ans=1ll*ans*(dg[i]+(v==i))%mod;if(v!=u&&v!=1){memcpy(idg,dg,sizeof(dg));inv[0]=inv[1]=1;for(int i=2;i<=n+1;++i) inv[i]=(mod-1ll*mod/i*inv[mod%i]%mod)%mod;f[v]=1,q.push(1);while(!q.empty()){int x=q.front();q.pop();f[x]=1ll*f[x]*inv[dg[x]+(x==v)]%mod;for(int i=hd[x];i;i=nt[i]){int y=to[i];f[y]=(f[y]+f[x])%mod,--idg[y];if(!idg[y]) q.push(y);}}ans=1ll*ans*(1-f[u]+mod)%mod;}printf("%d\n",ans);return 0;
}