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;
}

 

posted @ 2018-12-21 10:43  AKCqhzdy  阅读(122)  评论(0编辑  收藏  举报