[思路题][LOJ2290][THUWC2017]随机二分图:状压DP+期望DP
分析
考虑状压DP,令\(f[sta]\)表示已匹配状态是\(sta\)(\(0\)代表已匹配)时完美匹配的期望数量,显然\(f[0]=1\)。
一条边出现了不代表它一定在完美匹配内,这也导致很难去直接利用题目中的边组来解决问题。
对于第二类边组,如果把两条边分开考虑(可以理解为把一个第二类的边组看成两个第一类的边组)。如果只有一条边出现在了完美匹配中,此时的贡献是\(50\%\),显然是正确的。如果两条边都出现在了完美匹配中,此时的贡献是\(50\% \times 50\% = 25\%\),但是根据第二类边组的定义,两条边都出现在完美匹配中的贡献应该也是\(50\%\)。所以我们可以再添加一个只包含一条边的边组,这里面的边比较特殊,其连接了这个第二类边组的四个结点,出现概率为\(25\%\),来补充不足的贡献。
第三类边组的处理方法类似,添加一个只包含一条边的边组,边连接了四个结点,出现概率为\(-25\%\),来消去多余的贡献。
为了减小时间复杂度,每次转移时要确保能把最高位的\(1\)异或掉。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <map>
#define rin(i,a,b) for(int i=(a);i<=(b);i++)
#define rec(i,a,b) for(int i=(a);i>=(b);i--)
#define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
typedef long long LL;
using std::cin;
using std::cout;
using std::endl;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
const LL MOD=1e9+7,INV2=5e8+4,INV4=2.5e8+2;
int n,m,cnt,a[505];
LL p[505];
std::map<int,LL> mp;
LL dfs(int sta){
if(!sta) return 1;
if(mp.find(sta)!=mp.end()) return mp[sta];
LL ret=0;
rin(i,1,cnt){
if((sta|a[i])==sta&&(a[i]<<1)>sta)
ret=(ret+dfs(sta^a[i])*p[i])%MOD;
}
return mp[sta]=ret;
}
int main(){
n=read(),m=read();
rin(i,1,m){
int typ=read();
if(typ==0){
int x=read(),y=read();
a[++cnt]=((1<<(x-1))|(1<<(y+n-1)));
p[cnt]=INV2;
}
else if(typ==1){
int x1=read(),y1=read(),x2=read(),y2=read();
int temp1=((1<<(x1-1))|(1<<(y1+n-1))),temp2=((1<<(x2-1))|(1<<(y2+n-1)));
a[++cnt]=temp1,p[cnt]=INV2;
a[++cnt]=temp2,p[cnt]=INV2;
if(!(temp1&temp2)) a[++cnt]=(temp1|temp2),p[cnt]=INV4;
}
else{
int x1=read(),y1=read(),x2=read(),y2=read();
int temp1=((1<<(x1-1))|(1<<(y1+n-1))),temp2=((1<<(x2-1))|(1<<(y2+n-1)));
a[++cnt]=temp1,p[cnt]=INV2;
a[++cnt]=temp2,p[cnt]=INV2;
if(!(temp1&temp2)) a[++cnt]=(temp1|temp2),p[cnt]=MOD-INV4;
}
}
mp.clear();
printf("%lld\n",(1<<n)*dfs((1<<(n<<1))-1)%MOD);
return 0;
}
[思路题][LOJ2290][THUWC2017]随机二分图:状压DP+期望DP的更多相关文章
- P4547 [THUWC2017]随机二分图(状压,期望DP)
期望好题. 发现 \(n\) 非常小,应该要想到状压的. 我们可以先只考虑 0 操作. 最难的还是状态: 我们用 \(S\) 表示左部点有哪些点已经有对应点, \(T\) 表示右部点有哪些点已经有对应 ...
- 洛谷 P4547 & bzoj 5006 随机二分图 —— 状压DP+期望
题目:https://www.luogu.org/problemnew/show/P4547 https://www.lydsy.com/JudgeOnline/problem.php?id=5006 ...
- [LOJ2290] [THUWC2017] 随机二分图
题目链接 LOJ:https://loj.ac/problem/2290 洛谷:https://www.luogu.org/problemnew/show/P4547 Solution 首先考虑只有第 ...
- Luogu4547 THUWC2017 随机二分图 概率、状压DP
传送门 考虑如果只有$0$组边要怎么做.因为$N \leq 15$,考虑状压$DP$.设$f_i$表示当前的匹配情况为$i$时的概率($i$中$2^0$到$2^{N-1}$表示左半边的匹配情况,$2^ ...
- [BZOJ5006][LOJ#2290][THUWC2017]随机二分图(概率+状压DP)
https://loj.ac/problem/2290 题解:https://blog.csdn.net/Vectorxj/article/details/78905660 不是很好理解,对于边(x1 ...
- THUWC2017随机二分图
题面链接 洛谷 sol 唯一的重点是拆边... 0的不管,只看1.2. 先无论如何把两条边的边权赋为\(0.5\)然后我们发现如果两个都选了. 对于第一种边,我们发现如果\(\frac{1}{2} * ...
- 51nod 马拉松30 C(构二分图+状压dp)
题意 分析 考虑一个图能被若干简单环覆盖,那么一定是每个点恰好一个出度,恰好一个出度 于是类似最小路径覆盖的处理,我们可以把每个点拆成2个点i和i',如果有一条边(i,j),那么将i和j'连起来 那么 ...
- 题解 洛谷 P4547 【[THUWC2017]随机二分图】
根据题意,题目中所求的即为所有\(n!\)种完美匹配的各自的出现概率之和再乘上\(2^n\)的值. 发现\(n\)很小,考虑状压\(DP\).设\(f_{S,T}\)为左部图匹配情况为\(S\),右部 ...
- 【洛谷3343_BZOJ3925】[ZJOI2015]地震后的幻想乡(状压 DP_期望)
题目: 洛谷 3343 BZOJ 3925 分析: 谁给我说这是个期望概率神题的,明明没太大关系好吧 「提示」里那个结论哪天想起来再问 Jumpmelon 怎么证. 首先,由于开始修路前 \(e_i\ ...
随机推荐
- 【linux开发】Linux下配置java环境 安装eclipse
配置JDK环境 本文转自:http://www.cnblogs.com/fnng/archive/2013/01/30/2883815.html,有修改 下载 登录oracle的网站去下载JDK1.8 ...
- Sql注入校验
/// <summary> /// Sql注入校验 /// </summary> /// <param name="listWord">字符&l ...
- Java类加载器总结网址
http://blog.csdn.net/gjanyanlig/article/details/6818655
- Nginx跨域问题
Nginx跨域无法访问,通常报错: Failed to load http://172.18.6.30:8086/CityServlet: No 'Access-Control-Allow-Origi ...
- Java本周总结1
这两周我上认真的课应该就是李老师的课了/ 第一周主要跟我们讲述了java的发展史何java开发环境的搭建,带领我们走进了java,李老师的精彩讲述让我们对Java有了深刻的认识/. jdk下载安装包我 ...
- C语言I-博客作业04
这个作业属于那个课程 C语言程序设计II 这个作业要求在哪里 C语言I博客作业04 我在这个课程的目标是 掌握使用for循环语句实现指定次数的循环程序设计 这个作业在那个具体方面帮助我实现目标 在编写 ...
- kubeadm搭建K8s集群及Pod初体验
基于Kubeadm 搭建K8s集群: 通过上一篇博客,我们已经基本了解了 k8s 的基本概念,也许你现在还是有些模糊,说真的我也是很模糊的.只有不断地操作去熟练,强化自己对他的认知,才能提升境界. 我 ...
- java常用类之BigDecimal
BigDecimal 小数计算丢失精度问题 在计算机中,所有文件都是以二进制存储的,数字运算也是使用二进制进行计算的,因为计算机中不存在小数点,所以我们通常说的浮点数如float.double都是计算 ...
- numpy库的认识以及数组的创建
numpy库 numpy是Python数值计算最重要的基础包.大多数提供科学计算的包都是用NumPy的数组作为构建基础.numpy十分高效,基于NumPy的算法要比纯Python快10到100倍(甚至 ...
- rabitMQ-centos7安装
1.安装rabitMq之前需要安装Erlang cd /usr/local/ wget http://erlang.org/download/otp_src_18.3.tar.gz tar -zxvf ...