• UOJ37 【清华集训2014】主旋律


    Link
    然后枚举缩点之后的DAG的情况,考虑计算可行的边集方案数,再递归乘上所有scc的导出子图的答案。
    计算可行的边集方案数可以考虑dp,设(f_s)表示点集(s)的导出子图中使得子图形成一个DAG的边集方案数,那么可以得到转移

    [f_s=sumlimits_{tsubseteq swedge t eemptyset}(-1)^{|t|+1}f_{s-t}2^{cnt_{t,s-t}} ]

    其中(cnt_{s,t})表示的是起点在(s)中,终点在(t)中的边数。
    ((-1)^{|t|+1})是容斥系数,因为我们不能保证每个点都连出至少一条边,直接计算会算重。
    不难发现子集(t)的贡献系数仅与其scc数量的奇偶性有关,奇数为正偶数为负。
    那么我们就没有必要枚举缩点后的结果了,设(f_s)表示(s)的导出子图中使得图强联通的边集方案数,(g_s,h_s)表示(S)的导出子图中的使得图中形成奇/偶个scc,且scc之间相互没有边的边集方案数。
    那么我们有

    [f_s=2^{cnt_{s,s}}-sumlimits_{tsubseteq s,t eemptyset}(g_t-h_t)2^{cnt_{t,s-t}+cnt_{s-t,s-t}}\ g_s=sumlimits_{tsubseteq s,t eemptyset}f_th_{s-t}\ h_s=sumlimits_{tsubseteq s,t eemptyset}f_tg_{s-t} ]

    (s=t)的部分先转移(f)再转移(g,h)即可。

    #include<cstdio>
    using i64=long long;
    const int N=1<<15,P=1000000007;
    i64 to[N],e[N],f[N],g[N],pw[256];
    int read(){int x;scanf("%d",&x);return x;}
    void dec(i64&a,i64 b){a-=b,a+=a>>63&P;}
    int calc(int s,int t)
    {
        int ans=0;
        for(;s;s^=s&-s) ans+=__builtin_popcount(to[s&-s]&t);
        return ans;
    }
    int main()
    {
        int n=read(),m=read();
        for(int i=1,u,v;i<=m;++i) u=1<<(read()-1),v=1<<(read()-1),to[u]|=v;
        for(int i=1;i<1<<n;++i) e[i]=calc(i,i);
        for(int i=pw[0]=1;i<=210;++i) pw[i]=2*pw[i-1]%P;
        for(int i=1,j,k,s;i<1<<n;(g[i]+=f[i])%=P,++i)
        {
    	for(k=i&-i,s=i^k,j=(s-1)&s;j;j=(j-1)&s) dec(g[i],g[i^j^k]*f[j|k]%P);
    	if(i^k) dec(g[i],g[i^k]);
    	for(f[j=i]=pw[e[i]];j;j=(j-1)&i) dec(f[i],g[j]*pw[e[i^j]+calc(j,i^j)]%P);
        }
        printf("%lld",f[(1<<n)-1]);
    }
    
  • 相关阅读:
    SpringBoot基本配置
    Profile配置
    vue2.X使用LeanCloud
    Vue学习一 创建项目及项目总览
    工具使用:使用frp,反向代理内网到公网
    Unity的学习笔记(摇杆制作)
    Unity的学习笔记(XLua的初学用法并在lua中使用unity周期函数)
    Unity的学习笔记(射线检测)
    Unity的学习笔记(鼠标移动控制视角移动)
    Unity的学习笔记(UGUI文本逐个字输出)
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/13052666.html
Copyright © 2020-2023  润新知