DAG中每个点选一条入边就可以构成一棵有向树,所以如果没有环答案就是∏degreei。
考虑去掉含环的答案。可以看做把环缩点,剩下的点仍然可以任意选入边。于是去除的方案数即为∏degreei/∏degreek,k为环上点。
环相当于考虑新加入边的终点到起点的所有路径。设f[i]为i为起点的所有路径提供的上述贡献,则f[i]=Σf[k]/degree[i]。拓扑排序之后dp即可。
#include#include #include #include #include #include using namespace std;int read(){ int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') { if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f;}#define N 100010#define M 200010#define P 1000000007int n,m,p[N],u,v,degree[N],d[N],f[N],q[N],inv[N],t=0,ans=1;struct data{ int to,nxt;}edge[M];void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}void topsort(){ int head=0,tail=1;q[1]=1;memcpy(d,degree,sizeof(degree));d[v]--; while (tail =1;i--) { for (int j=p[q[i]];j;j=edge[j].nxt) f[q[i]]=(f[q[i]]+f[edge[j].to])%P; f[q[i]]=1ll*f[q[i]]*inv[degree[q[i]]]%P; } cout<<(ans-f[v]+P)%P; return 0;}