zoukankan      html  css  js  c++  java
  • [THUWC2017]随机二分图

    题目大意

    给一张二分图,有左部点和右部点。

    有三种边,第一种是直接从左部点连向右部点,出现概率为50%。

    第二种边一组里有两条边,这两条边同时出现或者不出现,概率都是50%。

    第三种边一组里有两条边,这两条边只能出现一条,概率都是50%。

    求这张图完美匹配数的期望

    题解

    一条边能够带来贡献的条件不是它出现了,而是它出现在了匹配中。所以我们应当直接计算每条边出现在最大匹配中的概率。

    第一种边不用研究。

    第二种边每一条条边出现在最大匹配中的概率都是50%。

    两条边出现在最大匹配中的概率也是50%。

    如果我们直接连两条50%的边的话,两条边同时出现的概率就是25%。

    所以我们补一条两组的边,概率为25%。

    第三种边同理,两条边出现在最大匹配中的概率是0%。

    所以我们补一组-25%的边就好了。

    dp的话,拿map记搜一下就好了。

    代码

    #include<iostream>
    #include<cstdio>
    #include<map>
    #define N 16
    using namespace std;
    typedef long long ll;
    const int mod=1e9+7;
    map<int,int>mp;
    map<int,int>::iterator it; 
    int lo[1<<N],tot,head[N],n,m;
    inline int rd(){
        int x=0;char c=getchar();bool f=0;
        while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        return f?-x:x;
    }
    inline ll power(ll x,ll y){
        ll ans=1;
        while(y){
            if(y&1)ans=ans*x%mod;x=x*x%mod;y>>=1;
        }
        return ans;
    }
    inline void MOD(ll &x){while(x>=mod)x-=mod;}
    struct edge{int n,to,l;}e[N*N*2];
    inline void add(int u,int v){
        int loo=lo[u&(-u)];
        e[++tot].n=head[loo];e[tot].to=u;head[loo]=tot;e[tot].l=v;
    }
    int DP(int s){
        if(!s)return 1;
        it=mp.find(s);
        if(it!=mp.end())return it->second;
        int loo=lo[s&(-s)];ll ans=0;
        for(int i=head[loo];i;i=e[i].n){
            int v=e[i].to;if((v&s)!=v)continue;
            ans+=1ll*DP(s^v)*e[i].l%mod;MOD(ans);
        }
        return mp[s]=ans;
    }
    int main(){
        n=rd();m=rd();int u1,v1,u2,v2,ma=(1<<n)-1,opt;
        ll n2=power(2,mod-2),n4=power(4,mod-2);
        lo[1]=1;int cc=1;
        for(int i=2;i<=n;++i)cc<<=1,lo[cc]=i;
        for(int i=1;i<=m;++i){
            opt=rd();
            if(opt==0){
                u1=rd();v1=rd();u1--;v1--;
                int s1=(1<<u1)|(1<<v1+n); 
                add(s1,n2);
            } 
            else if(opt==1){
                u1=rd()-1;v1=rd()-1;u2=rd()-1;v2=rd()-1;
                int s1=(1<<u1)|(1<<v1+n),s2=(1<<u2)|(1<<v2+n);
                add(s1,n2);add(s2,n2); 
                if(!(s1&s2)){
                    add(s1|s2,n4);
                }
            }
            else{
                u1=rd()-1;v1=rd()-1;u2=rd()-1;v2=rd()-1;
                int s1=(1<<u1)|(1<<v1+n),s2=(1<<u2)|(1<<v2+n);
                add(s1,n2);add(s2,n2); 
                    if(!(s1&s2)){
                    add(s1|s2,mod-n4);
                }
            }
        }
        cout<<1ll*DP(ma|(ma<<n))*power(2,n)%mod;
        return 0;
    } 
  • 相关阅读:
    jquery deferred对象
    一张图道尽Javascript的原型继承
    Reflection
    vim操作
    转载:HTTP调试工具:Fiddler的使用方法介绍
    转载:计算机网络面试题
    20120810
    new pad不能用usb充电的解决方法
    20120416
    Lua入门——环境安装
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/10297240.html
Copyright © 2011-2022 走看看