版权声明:虽然博主很菜,但是还是请注明出处(我觉得应该没人偷我的博客) https://blog.csdn.net/qq_43346903/article/details/88981753
题意:给个DAG和一条额外的边,求以1为根的有向生成树个数
分析:如果没有额外的边,那么考虑乘法原理得到答案就是
加上额外的边后,可能生成环(如果没有就一样的)
多出来的选择就是环上的点都选了环上的父亲
那么我们设
是
到
(给出的额外边)上产生的贡献,转移就是
Code:
#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=1e5+5;
int vis[N<<1],head[N<<1],nxt[N<<1],tot=0;
int in[N],sum=1;
inline void add(int x,int y){vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;}
inline int ksm(int a,int b){int res=1; for(;b;b>>=1){if(b&1) res=(ll)res*a%mod;a=(ll)a*a%mod;} return res;}
int pt[N],s,t,f[N];
void dfs(int v){
if(pt[v]) return;
pt[v]=1;
if(v==t) {f[v]=(ll)sum*ksm(in[v],mod-2)%mod;return;}
for(int i=head[v];i;i=nxt[i])
dfs(vis[i]),f[v]=(f[v]+f[vis[i]])%mod;
f[v]=(ll)f[v]*ksm(in[v],mod-2)%mod;
}
int ans=1;
int main(){
int n=read(),m=read();s=read(),t=read();
for(int x,y,i=1;i<=m;i++) x=read(),y=read(),add(y,x),++in[y];
in[1]++;
for(int i=1;i<=n;++i) {
if(i==t) ans=(ll)(in[i]+1)*ans%mod;
else ans=(ll)in[i]*ans%mod;
sum=(ll)in[i]*sum%mod;
}
dfs(s);
ans=(ans+mod-f[s])%mod;
cout<<ans<<endl;
return 0;
}