loj2290 随机二分图

题意:有一个左右各n个点的二分图,对于连边组有一些性质:1号组的一条边,有50%的概率出现。2号组两条边,有50%的概率同时出现,50%的概率同时不出现。3号组两条边,有50%的概率出现第一条,有50%的概率出现第二条。问完美匹配(所有点都有匹配)方案数的期望*2^n。n<=15。

 

标程:

 1 #include<cstdio>
 2 #include<map>
 3 using namespace std;
 4 typedef long long ll;
 5 const int mod=1e9+7;
 6 const int inv2=5e8+4;
 7 const int inv4=25e7+2;
 8 const int inv_4=75e7+5;
 9 const int N=1000;
10 int read()
11 {
12     int x=0;char ch=getchar();
13     while (ch<'0'||ch>'9') ch=getchar();
14     while ('0'<=ch&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
15     return x;
16 }
17 struct node{int v,p;node(){}node(int A,int B){v=A;p=B;}}e[N];
18 map<int,int> mp;
19 int n,m,op,x,y,cnt,id,id2;
20 int dp(int zt)
21 {
22     if (!zt) return 1;
23     map<int,int>::iterator t=mp.find(zt);
24     if (t!=mp.end()) return t->second;
25     int ans=0;
26     for (int i=1;i<=cnt;i++)
27       if ((e[i].v&zt)==e[i].v&&e[i].v*2>zt)
28         ans=((ll)ans+(ll)dp(zt^e[i].v)*e[i].p%mod)%mod;
29     return mp[zt]=ans;
30 }
31 int main()
32 {
33     n=read();m=read();
34     for (int i=1;i<=m;i++)
35     {
36         op=read();x=read();y=read();
37         id=(1<<x-1)|(1<<n+y-1);
38         e[++cnt]=node(id,inv2);
39         if (op) 
40         {
41            x=read(),y=read();
42            id2=(1<<x-1)|(1<<n+y-1);
43            e[++cnt]=node(id2,inv2);
44            if (!(id&id2))//有重合端点的话不用考虑 
45              if (op==1) e[++cnt]=node(id|id2,inv4);
46              else e[++cnt]=node(id|id2,inv_4);
47         }    
48     }
49     printf("%d\n",((ll)dp((1<<(2*n))-1)<<n)%mod);
50     return 0;
51 }

 

易错点:1.注意2和3组的两条边如果有重复端点的话是不用考虑加组合边的,一定不会同时选这两条边。

 

题解:dp

如果都是1号组的点,也就是边没有依赖出现关系。那么直接dp。f[state]表示在state的匹配状态下完美匹配数的期望。

为了不算重,按照套路应该选取一个特殊点v,比如编号最大点、lowbit等。

f[state]=sigma(f[state^v^match_v]*p),p=50%,match_v表示与v相连的另一点。

状态数有sigma(C(n,i)^2)=sigma(C(n,i)*C(n,n-i))=范德蒙德卷积形式=C(2n,n)≈1.6*1e8,用map记录改成记忆化搜索就好了。

冷静分析第2组点和第3组点的特征:对于第2组点,如果两条边都不选或只选一条,概率则为0和50%和组1的情况一样;但当两条都选时,组1的概率为50%*50%=25%,而实际应该是50%,对策是再加一条包含这两条边的组合边,概率为25%,这样两种加起来就是50%了。

同理对于第3组点,如果都不选或只选一条,概率是等同于组1的选法。而都选的概率应该是0,于是加一条概率为-25%的组合边。

按照组1的情况转移即可。

转载于:https://www.cnblogs.com/Scx117/p/8762480.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值