[bzoj5006][DP]Bipartite 随机二分图

版权声明:神的bolg... https://blog.csdn.net/Rose_max/article/details/86488610

Description

传送门…

题解

感觉直接做也是可以的啊…只不过好像很麻烦
第一种边直接做了不用理…
现在要把2,3两种边拆开,让他变成第一种边做
第二种拆成两条不相关的 50 % 50\% 的边,显然单选任意一条边时候贡献与两条出现是相同的,只有两条边都计入完备匹配的时候概率会变成 25 % 25\% ,所以可以加一条强行要让四个点连起来的边,概率 25 % 25\%
第三种类似上面,概率变成 25 % -25\% 即可
然后可以一个 d p [ u 1 ] [ u 2 ] dp[u1][u2] 表示 u 1 , u 2 u1,u2 这个状态的点完备匹配的期望是什么
转移的话我们枚举编号最小的点是和谁匹配的然后去到下一个状态
记忆化搜一搜

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#include<set>
#define LL long long
#define mp(x,y) make_pair(x,y)
#define pll pair<long long,long long>
#define pii pair<int,int>
using namespace std;
inline int read()
{
	int f=1,x=0;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int stack[20];
inline void write(LL x)
{
	if(x<0){putchar('-');x=-x;}
    if(!x){putchar('0');return;}
    int top=0;
    while(x)stack[++top]=x%10,x/=10;
    while(top)putchar(stack[top--]+'0');
}
inline void pr1(int x){write(x);putchar(' ');}
inline void pr2(LL x){write(x);putchar('\n');}
const LL mod=1e9+7;
const LL inv=500000004;
const LL inv1=250000002;
const int MAXMASK=(1<<15);
const int MAXM=305;
const int MAXN=20;

struct node{int x,y,u,v,next;LL ar;}a[MAXM];int len,last[MAXN];
void ins(int x,int y,int u,int v,LL ar)
{
	len++;
	a[len].x=x;a[len].y=y;a[len].u=u;a[len].v=v;a[len].next=last[x];last[x]=len;
	a[len].ar=ar;
}
int bin[35],fac[MAXMASK],n,m;
map<int,LL> mp[MAXMASK],vis[MAXMASK];
int lowbit(int x){return fac[x&-x];}
void ad(LL &x,LL y){x+=y;if(x>=mod)x-=mod;}
LL dp(int u1,int u2)
{
	if(!u1&&!u2)return 1;
	if(vis[u1][u2])return mp[u1][u2];
	vis[u1][u2]=1;
	int x=lowbit(u1);LL ret=0;
	for(int k=last[x];k;k=a[k].next)
	{
		int y=a[k].y;if(u2&bin[y])
		{
			if(!a[k].u)ad(ret,(a[k].ar*dp(u1^bin[x],u2^bin[y])%mod+mod)%mod);
			else if(((u1^bin[x])&bin[a[k].u])&&((u2^bin[y])&bin[a[k].v]))ad(ret,(a[k].ar*dp(u1^bin[x]^bin[a[k].u],u2^bin[y]^bin[a[k].v])%mod+mod)%mod);
		}
	}
	return mp[u1][u2]=ret;
}
int main()
{
	bin[1]=1;for(int i=2;i<=20;i++)bin[i]=bin[i-1]<<1;
	for(int i=1;i<=15;i++)fac[bin[i]]=i;
	n=read();m=read();
	for(int i=1;i<=m;i++)
	{
		int opt=read(),u1=read(),u2=read();
		if(opt)
		{
			int u3=read(),u4=read();
			if(u1>u3)swap(u1,u3),swap(u2,u4);
			ins(u1,u2,0,0,inv);ins(u3,u4,0,0,inv);
			if(u1==u3||u2==u4)continue;
			if(opt==1)ins(u1,u2,u3,u4,inv1);
			else ins(u1,u2,u3,u4,-inv1);
		}
		else ins(u1,u2,0,0,inv);
	}
	pr2(dp(bin[n+1]-1,bin[n+1]-1)*bin[n+1]%mod);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Rose_max/article/details/86488610