根据题意,题目中所求的即为所有\(n!\)种完美匹配的各自的出现概率之和再乘上\(2^n\)的值。

发现\(n\)很小,考虑状压\(DP\)。设\(f_{S,T}\)为左部图匹配情况为\(S\),右部图匹配情况为\(T\)的期望,可以得到转移为:

\[
f_{S,T}=\sum_{x \subseteqq S \land y \subseteqq T }f_{S \oplus x,T \oplus y} \times p_e

\]

其中\(x,y\)为边\(e\)的在两个部图的两个端点,\(p_e\)为这条边的出现概率,转移的含义为加上\(e\)这条边后\(x\)和\(y\)实现了匹配。

发现直接这样转移会算重,所以要事先固定一种转移顺序,可以是每次在\(S\)中去除最高位来转移,也就是从低位向高位转移,这样就保证不会算重了。

然后考虑如何解决每条边的出现概率,第一组边不用特殊考虑,概率为\(\frac{1}{2}\)。考虑是否可以把第二组和第三组边也转化为第一种的形式。可以先将第二组和第三组边的两条边都以概率为\(\frac{1}{2}\)加入,对于第二组边,这时两条边同时出现的概率为\(\frac{1}{4}\),不符合题目\(\frac{1}{2}\)的要求,因此再加入同时选这两条边的情况,概率为\(\frac{1}{4}\),对于第三组边,再加入同时选这两条边的情况,概率为\(-\frac{1}{4}\)。根据期望的线性性,发现这样处理是正确的,并且恰好符合了题目的要求。

第二组和第三组边中,若两条边有交集,即两条边为一个点连向另外两个点,此时是不用加上同时选这两条边的情况的,因为题目所求为完美匹配,一个点匹配两个点的情况是不存在的。

处理完边后,记忆化搜索来实现状压\(DP\)即可。

\(code:\)

#include<bits/stdc++.h>
#define maxs 70010
#define p 1000000007
#define inv2 500000004
#define inv4 250000002
#define sta(x) (1<<(x-1))
using namespace std;
typedef long long ll;
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag)x=-x;
}
int n,m,cnt;
map<int,ll> f[maxs];
struct node
{
ll s,t,v;
}e[maxs];
ll dp(int S,int T)
{
if(!S) return 1;
if(f[S].count(T)) return f[S][T];
for(int i=1;i<=cnt;++i)
{
ll s=e[i].s,t=e[i].t,v=e[i].v;
if((S|s)!=S||(T|t)!=T||S>=(s<<1)) continue;
f[S][T]=(f[S][T]+dp(S^s,T^t)*v%p)%p;
}
return f[S][T];
}
int main()
{
read(n),read(m);
for(int i=1;i<=m;++i)
{
int opt,x,y;
read(opt),read(x),read(y),e[++cnt]=(node){sta(x),sta(y),inv2};
if(opt)
{
read(x),read(y);
if(!((sta(x)&e[cnt].s)||(sta(y)&e[cnt].t)))
{
cnt++;
if(opt==1) e[cnt]=(node){sta(x)|e[cnt-1].s,sta(y)|e[cnt-1].t,inv4};
else e[cnt]=(node){sta(x)|e[cnt-1].s,sta(y)|e[cnt-1].t,p-inv4};
}
e[++cnt]=(node){sta(x),sta(y),inv2};
}
}
printf("%lld",dp((1<<n)-1,(1<<n)-1)*(1<<n)%p);
return 0;
}

题解 洛谷 P4547 【[THUWC2017]随机二分图】的更多相关文章

  1. P4547 [THUWC2017]随机二分图(状压,期望DP)

    期望好题. 发现 \(n\) 非常小,应该要想到状压的. 我们可以先只考虑 0 操作. 最难的还是状态: 我们用 \(S\) 表示左部点有哪些点已经有对应点, \(T\) 表示右部点有哪些点已经有对应 ...

  2. 【BZOJ2830/洛谷3830】随机树(动态规划)

    [BZOJ2830/洛谷3830]随机树(动态规划) 题面 洛谷 题解 先考虑第一问. 第一问的答案显然就是所有情况下所有点的深度的平均数. 考虑新加入的两个点,一定会删去某个叶子,然后新加入两个深度 ...

  3. [LOJ2290] [THUWC2017] 随机二分图

    题目链接 LOJ:https://loj.ac/problem/2290 洛谷:https://www.luogu.org/problemnew/show/P4547 Solution 首先考虑只有第 ...

  4. 题解 洛谷P5018【对称二叉树】(noip2018T4)

    \(noip2018\) \(T4\)题解 其实呢,我是觉得这题比\(T3\)水到不知道哪里去了 毕竟我比较菜,不大会\(dp\) 好了开始讲正事 这题其实考察的其实就是选手对D(大)F(法)S(师) ...

  5. 题解 洛谷 P3396 【哈希冲突】(根号分治)

    根号分治 前言 本题是一道讲解根号分治思想的论文题(然鹅我并没有找到论文),正 如论文中所说,根号算法--不仅是分块,根号分治利用的思想和分块像 似却又不同,某一篇洛谷日报中说过,分块算法实质上是一种 ...

  6. 题解-洛谷P5410 【模板】扩展 KMP(Z 函数)

    题面 洛谷P5410 [模板]扩展 KMP(Z 函数) 给定两个字符串 \(a,b\),要求出两个数组:\(b\) 的 \(z\) 函数数组 \(z\).\(b\) 与 \(a\) 的每一个后缀的 L ...

  7. 题解-洛谷P4229 某位歌姬的故事

    题面 洛谷P4229 某位歌姬的故事 \(T\) 组测试数据.有 \(n\) 个音节,每个音节 \(h_i\in[1,A]\),还有 \(m\) 个限制 \((l_i,r_i,g_i)\) 表示 \( ...

  8. 题解-洛谷P4724 【模板】三维凸包

    洛谷P4724 [模板]三维凸包 给出空间中 \(n\) 个点 \(p_i\),求凸包表面积. 数据范围:\(1\le n\le 2000\). 这篇题解因为是世界上最逊的人写的,所以也会有求凸包体积 ...

  9. 题解-洛谷P4859 已经没有什么好害怕的了

    洛谷P4859 已经没有什么好害怕的了 给定 \(n\) 和 \(k\),\(n\) 个糖果能量 \(a_i\) 和 \(n\) 个药片能量 \(b_i\),每个 \(a_i\) 和 \(b_i\) ...

随机推荐

  1. SpringCloud 入门(一)

    本人也是刚接触springcloud,现在先将创建项目的过程记录下来,springcloud的理解日后再慢慢补齐,最好还是自己参考官方文档的介绍 使用工具:IDEA IDEA创建springcloud ...

  2. 一位老程序员说,有这份python3的开发指南,月薪能突破20K

    推荐视频: AI人工智能识别技术_第一节AI人工智能识别技术_第二节Python基础案例之教你如何查询对方IP_第一节Python基础案例之教你如何查询对方IP_第二节 有程序员说,这份python3 ...

  3. ElasticSearch--validate验证搜索语句是否合法或者存在语法错误

    GET /accounts/person/_validate/query?explain { "query":{ "match": { "user&q ...

  4. java基础-循环标签

    outer: for innter: for break outer//跳出整个循环: continue outer//结束本次外循环的循环 break inner; continute inner; ...

  5. .NET Core下开源任务调度框架Hangfire

    今天无意中发现了一个很好用的任务调度框架.Hangfire作为一款高人气且容易上手的分布式后台执行服务,支持多种数据库.在 .net core的环境中,由Core自带的DI管理着生命周期. 相较于qu ...

  6. Python-使用百度文字识别API实现的文字识别工具

    import requests import base64 import keyboard import mouse import time import os from PIL import Ima ...

  7. Oauth2.0认证流程

  8. 面向切面对象AOP

    前言 面向切面编程(思想)AOP Aspect Oriented  Programming,是面向对象基础上 更关注最终目标 而不关注中间的小目标,简而言之,就是我们的目标(例如constroller ...

  9. PHP实现邮箱验证码验证功能

    *文章来源:https://blog.egsec.cn/archives/623  (我的主站) *本文将主要说明:PHP实现邮箱验证码验证功能,通过注册或登录向用户发送身份确认验证码,并通过判断输入 ...

  10. 来看下css边框阴影怎么设置?这些方法掌握后工作更轻松

    我们在网页设计中,通常会使用ps工具来达到图片或者边框阴影.立体等效果.但是如果一些基础效果都需要用p图来完成那就显得效率比较低了.其实可以使用CSS来设置边框阴影,下面本篇文章来给大家介绍一下. 在 ...