zoukankan      html  css  js  c++  java
  • BZOJ4011 HNOI2015落忆枫音(动态规划+拓扑排序)

      DAG中每个点选一条入边就可以构成一棵有向树,所以如果没有环答案就是∏degreei

      考虑去掉含环的答案。可以看做把环缩点,剩下的点仍然可以任意选入边。于是去除的方案数即为∏degreei/∏degreek,k为环上点。

      环相当于考虑新加入边的终点到起点的所有路径。设f[i]为i为起点的所有路径提供的上述贡献,则f[i]=Σf[k]/degree[i]。拓扑排序之后dp即可。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    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 1000000007
    int 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<n)
        {
            int x=q[++head];
            for (int i=p[x];i;i=edge[i].nxt)
            {
                d[edge[i].to]--;
                if (!d[edge[i].to]) q[++tail]=edge[i].to;
            }
        }
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4011.in","r",stdin);
        freopen("bzoj4011.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read(),u=read(),v=read();
        for (int i=1;i<=m;i++)
        {
            int x=read(),y=read();
            addedge(x,y);degree[y]++;
        }
        inv[1]=1;for (int i=2;i<=n;i++) inv[i]=P-1ll*(P/i)*inv[P%i]%P;
        degree[v]++;
        for (int i=2;i<=n;i++) ans=1ll*ans*degree[i]%P;
        if (v==1) {cout<<ans;return 0;}
        topsort();f[u]=ans;
        for (int i=n;i>=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;
    }
  • 相关阅读:
    [原]音视频播放笔记
    [原]很多时候, 错误源于自己
    [原]找工作之tj
    [原]昨天碰到的一个诡异问题
    [原]硬盘分区规划
    [原]编程手记2008.08.26
    [原]编程手记2008.08.28
    eclipse 某些java文件乱码
    图片垂直居中,兼容ie6
    ul里不能直接嵌套div
  • 原文地址:https://www.cnblogs.com/Gloid/p/9820143.html
Copyright © 2011-2022 走看看