THUWC2017隨機二分圖

題面連接

洛谷url

sol

惟一的重點是拆邊。。。spa

0的無論,只看一、2。.net

先不管如何把兩條邊的邊權賦爲$0.5$而後咱們發現若是兩個都選了。code

對於第一種邊,咱們發現若是$\frac{1}{2} * \frac{1}{2}=\frac{1}{4}$,但咱們實際上須要的是$\frac{1}{2}$因此咱們連一條兩條邊都在內的邊,權值爲$\frac{1}{4}$get

同理,第二種就是$-\frac{1}{4}$string

而後就是狀壓$dp$it

#include<map>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define gt getchar()
#define ll long long
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
inline int in()
{
	int k=0;char ch=gt;
	while(ch<'-')ch=gt;
	while(ch>'-')k=k*10+ch-'0',ch=gt;
	return k;
}
const int YL=1e9+7,inv2=5e8+4,inv4=2.5e8+2;
inline int MO(const int &a){return a>=YL?a-YL:a;}
std::map<int,int>f[1<<16];
#define mk(x,y) ((1<<(x-1))|(1<<(y+n-1)))
int S[1<<16],v[1<<16],cnt,n,m;
int dp(int S_now)
{
	if(!S_now)return 1;
	int T_0=S_now>>n,S_0=S_now&((1<<n)-1);
	if(f[T_0].count(S_0))return f[T_0][S_0];
	int &res=f[T_0][S_0];
	for(int i=1;i<=cnt;++i)
	{
		int T=S[i];
		if((S_now|T)==S_now&&S_now<(T<<1))
			res=MO(res+1ll*dp(S_now^T)*v[i]%YL);
	}
	return res;
}
int main()
{
	n=in(),m=in();
	for(int i=1;i<=m;++i)
	{
		int op=in(),x=in(),y=in();
		int S1=mk(x,y);S[++cnt]=S1,v[cnt]=inv2;
		if(op)
		{
			x=in(),y=in();
			int S2=S[++cnt]=mk(x,y);v[cnt]=inv2;
			if(S[cnt]&S1)continue;
			S[++cnt]=S1|S2;
			v[cnt]=(op==1?inv4:YL-inv4);
		}
	}
	printf("%lld\n",(1ll<<n)*dp((1<<2*n)-1)%YL);
	return 0;
}
相關文章
相關標籤/搜索