bzoj4011: [HNOI2015]落忆枫音
首先如果是有向无环图的话就是度数之积了
于是我们需要减去构成环的情况,这个环一定是过新加的边的
那么不合法的情况就是选了yy->xx的一条路径,其他点乱选
进行DP,fi表示选yy->i的路径其他点乱选的方案数,fv= sigema((u,v)属于E) fu / v的度数
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; const LL mod=1e9+7; void exgcd(LL a,LL b,LL &x,LL &y) { if(a==0) { x=0;y=1; return ; } else { LL tx,ty; exgcd(b%a,a,tx,ty); x=ty-b/a*tx; y=tx; } } LL inv(LL A) { LL B=mod,x,y; exgcd(A,B,x,y); return (x%B+B)%B; } struct node { int x,y,next; }a[210000];int len,last[110000]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } int du[110000],dd[110000]; int top,sta[110000],f[110000]; int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int n,m,x,y,xx,yy; scanf("%d%d%d%d",&n,&m,&xx,&yy); memset(du,0,sizeof(du)); memset(dd,0,sizeof(dd)); for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); ins(x,y);du[y]++,dd[y]++; } LL sum=1; du[yy]++,dd[yy]++; for(int i=2;i<=n;i++) sum=(sum*du[i])%mod; du[yy]--; if(xx!=yy&&yy!=1) { top=0;sta[++top]=1; f[yy]=sum*inv(dd[yy])%mod; while(top!=0) { x=sta[top];top--; for(int k=last[x];k;k=a[k].next) { y=a[k].y; du[y]--,f[y]=(f[y]+f[x]*inv(dd[y]))%mod; if(du[y]==0)sta[++top]=y; } } } printf("%lld\n",((sum-f[xx])%mod+mod)%mod); return 0; }
pain and happy in the cruel world.