• 洛谷P4547 [THUWC2017]随机二分图


    题目描述

    题解

    考虑一个完美匹配出现的概率 $ imes 2^n$ 对答案的贡献,初始是 $1$ ,如果有出现一组 $t=2$ 的边的话,那贡献就是 $0$ ,否则每出现一组 $t=1$ 的边就要 $ imes 2$ ,所以有个暴力的 $ ext{dp}$ : $f[s1][s2]$ 表示左边出现点的状态为 $s1$ ,右边为 $s2$ 的答案,为了避免重复我们每次挑 $s1$ 中编号最小的点进行转移,即 $f[s1][s2]=sum_{y in s2}f[s1 wedge x][s2 wedge y]$ ,考虑如果 $(x,y)$ 有一组 $t=1$ 的边 $(u,v)$ 也在 $s1,s2$ 集合中的话,那要再加上 $f[s1 wedge x wedge u][s2 wedge y wedge v]$ ,反之如果有一组 $t=2$ 的在集合中的话就要扣掉,记忆化搜索即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int P=1e9+7;map<int,int>f;
    int n,m,k,a[15][15],c[1<<15],b[15][15][2];
    int X(int x){return x>=P?x-P:x;}
    int F(int i,int j){
        if (f.count(i<<n|j)) return f[i<<n|j];
        int w=0,x=i&-i,u,v;
        for (int y=j&-j,k=j;k;k^=y,y=k&-k){
            if (!~a[c[x]][c[y]]) continue;
            w=X(w+F(i^x,j^y));
            u=b[c[x]][c[y]][0];v=b[c[x]][c[y]][1];
            if (a[c[x]][c[y]] && (u&i) && (v&j) && u!=x && v!=y){
                if (a[c[x]][c[y]]&1) w=X(w+F(i^x^u,j^y^v));
                else w=X(w+P-F(i^x^u,j^y^v));
            }
        }
        return f[i<<n|j]=w;
    }
    int main(){
        cin>>n>>m;k=1<<n;
        for (int i=0;i<n;i++) c[1<<i]=i;
        memset(a,-1,sizeof a);
        for (int x,y,u,v,o,i=1;i<=m;i++){
            scanf("%d%d%d",&o,&x,&y);
            x--;y--;a[x][y]=o;
            if (o){
                scanf("%d%d",&u,&v);
                u--;v--;a[u][v]=o;
                b[x][y][0]=1<<u;b[x][y][1]=1<<v;
                b[u][v][0]=1<<x;b[u][v][1]=1<<y;
            }
        }
        f[0]=1;
        printf("%d
    ",F(k-1,k-1));
        return 0;
    }
  • 相关阅读:
    C++11线程池
    muduo的事件处理(Reactor模型关键结构)
    sed和awk
    gdb
    C#访问级别
    C#表达式树浅析
    C#并发实战Parallel.ForEach使用
    c#获取本月有哪些周六、周日
    重装了Devexpress后项目报Dll引用找不到问题解决办法
    C#单例模式
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/12343276.html
Copyright © 2020-2023  润新知