考虑依然用随便选的答案减去含环的答案。
含环的答案就是\prod_{x不在环上}#{x的入度},也就是所以点的度数的乘积除以在环上的点答案,对环做dp即可。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
#define N 100010
#define M 200010
#define mod 1000000007
#define lint long long
#define clr(a,n) memset(a,0,sizeof(int)*((n)+1))
#define inv(x) fast_pow(x,mod-2)
using namespace std;
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
inline int mol(int x) { return x%=mod,(x<0?x+mod:x); }
struct edges{
int to,pre;
}e[M];int h[N],d[N],dv[N],tms[N],etop,u[M],v[M],dp[N];queue<int> q;
inline int add_edge(int u,int v) { return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop; }
inline int fast_pow(int x,int k,int ans=1)
{ for(;k;k>>=1,x=(lint)x*x%mod) (k&1)?ans=(lint)ans*x%mod:0;return ans; }
inline int toposort(int s,int n,int ans=1)
{
while(!q.empty()) q.pop();int c=0;
for(int i=1;i<=n;i++) if(!d[i]) q.push(i);
for(int i=2;i<=n;i++) ans=(lint)ans*d[i]%mod;
while(!q.empty())
{
int x=q.front();tms[++c]=x,q.pop();
for(int i=h[x],y;i;i=e[i].pre)
if(!(--d[y=e[i].to])) q.push(y);
}
return c<n?ans=0:ans;
}
inline int getans(int s,int t,int n)
{
clr(dp,n),dp[s]=1;
for(int i=1;i<=n;i++) dv[i]=inv(d[i]);
for(int i=2;i<=n;i++) dp[s]=(lint)dp[s]*d[i]%mod;
for(int j=1,x=0;j<=n;j++) if(dp[x=tms[j]])
{
dp[x]=(lint)dp[x]*dv[x]%mod;
for(int i=h[x];i;i=e[i].pre)
(dp[e[i].to]+=dp[x])%=mod;
}
return dp[t];
}
int main()
{
int n=inn(),m=inn(),x=inn(),y=inn(),ans=1;
for(int i=1;i<=m;i++) u[i]=inn(),v[i]=inn();
for(int i=1;i<=m;i++) add_edge(u[i],v[i]),d[v[i]]++;
add_edge(x,y),d[y]++;
if(ans=toposort(1,n)) return !printf("%d\n",ans);
clr(h,n),etop=0,clr(d,n);
for(int i=1;i<=m;i++) add_edge(u[i],v[i]),d[v[i]]++;
toposort(1,n),clr(d,n),d[y]++,ans=1;
for(int i=1;i<=m;i++) d[v[i]]++;
for(int i=2;i<=n;i++) ans=(lint)ans*d[i]%mod;d[y]--;
return !printf("%d\n",mol(ans-getans(y,x,n)));
}