落忆枫音
首先对于一张拓扑图,生成树的个数ans-->除根节点以外的节点的入度之积
但是加了一条边以后就变得不拓扑了,所以要减去所产生的不合法的情况,即统计由Y到X的路径条数
对于包含这样的路径的不合法的"树",会有-->所有不包含于这条路径的点的入度的乘积种
即-->ans/du[所有属于路径的节点]
我们用f[i]表示节点i到Y的方案数,边界条件f[Y]=ans,除法用逆元搞定
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 typedef long long i64; 5 #define mod 1000000007 6 #define maxn 100005 7 #define maxm 200005 8 int cnt,v[maxm<<1],next[maxm<<1],first[maxn]; 9 int n,m,X,Y,q[maxn],in[maxn],du[maxn]; 10 i64 f[maxn]; 11 int read(){ 12 int tmp=0; 13 char ch=0; 14 while(!isdigit(ch))ch=getchar(); 15 while(isdigit(ch)){ 16 tmp=tmp*10+ch-'0'; 17 ch=getchar(); 18 } 19 return tmp; 20 } 21 void add(int st,int end){ 22 v[++cnt]=end; 23 next[cnt]=first[st]; 24 first[st]=cnt; 25 } 26 i64 qp(i64 bs,int x){ 27 i64 sum=1LL; 28 while(x){ 29 if(x&1)sum=sum*bs%mod; 30 bs=bs*bs%mod; 31 x>>=1; 32 } 33 return sum; 34 } 35 void topo(){ 36 int head=0,tail=0; 37 for(int i=1;i<=n;i++) 38 if(!in[i])q[++tail]=i; 39 while(head<tail){ 40 int x=q[++head]; 41 f[x]=f[x]*qp(du[x],mod-2)%mod; 42 for(int e=first[x];e;e=next[e]){ 43 f[v[e]]=(f[v[e]]+f[x])%mod; 44 if(!--in[v[e]])q[++tail]=v[e]; 45 } 46 } 47 } 48 int main(){ 49 n=read(),m=read(),X=read(),Y=read(); 50 for(int i=1;i<=m;i++){ 51 int a,b; 52 a=read(),b=read(); 53 add(a,b); 54 in[b]++,du[b]++; 55 } 56 du[Y]++; 57 i64 ans=1LL; 58 for(int i=2;i<=n;i++) 59 ans=ans*du[i]%mod; 60 if(Y==1||X==Y){ 61 printf("%lld\n",ans); 62 return 0; 63 } 64 f[Y]=ans; 65 topo(); 66 ans=(ans-f[X]+mod)%mod; 67 printf("%lld\n",ans); 68 return 0; 69 } 70