几个重点:
1.从每个点任选一条入边,都可以成为一个树形图。
2.于是考虑所有答案减去有环的答案。
3.将要求的东西形式化表示出来,然后发现可以直接dp。。
好厉害啊。。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define maxv 100050 #define maxe 200050 #define mod 1000000007 using namespace std; long long n,m,x,y,a,b,d[maxv],dp[maxv],inv[maxv],ans=1,nume=1,g[maxv],dv[maxv]; queue <long long> q; struct edge { long long v,nxt; }e[maxe]; void addedge(long long u,long long v) { e[++nume].v=v; e[nume].nxt=g[u]; g[u]=nume; } void get_table() { inv[1]=1; for (long long i=2;i<=n;i++) inv[i]=(-(mod/i)*inv[mod%i]%mod+mod)%mod; } void topusort() { for (long long i=1;i<=n;i++) { dv[i]=d[i]; if (!d[i]) q.push(i); } while (!q.empty()) { long long head=q.front();q.pop(); for (long long i=g[head];i;i=e[i].nxt) { long long v=e[i].v; dp[v]+=dp[head]*inv[dv[v]]%mod;if (dp[v]>mod) dp[v]%=mod; if (!--d[v]) q.push(v); } } } int main() { scanf("%lld%lld%lld%lld",&n,&m,&x,&y);d[y]++; for (long long i=1;i<=m;i++) { scanf("%lld%lld",&a,&b); d[b]++;addedge(a,b); } for (long long i=2;i<=n;i++) ans=(ans*d[i])%mod; if (y==1) {printf("%d\n",ans);return 0;} get_table(); dp[y]=ans*inv[d[y]]%mod;d[y]--; topusort(); printf("%lld\n",(ans-dp[x]+mod)%mod); return 0; }