dalao的博客
以前觉得很神的题。
分拆条件即可。
状压存边真是秀到我了。
#include<bits/stdc++.h>
#define mod 1000000007
#define maxn 16
using namespace std;
#define Siz 20000007
#define Hashmod 10000007
#define inv2 (mod+1)/2
#define inv4 (mod+1)/4
int info[Hashmod],sta[Siz],val[Siz],Prev[Siz],tot;
int n,m;
int Query(int st)
{
for(int i=info[st%Hashmod];i;i=Prev[i])
if(sta[i] == st)
return val[i];
return -1;
}
void Insert(int st,int v)
{
++tot;
sta[tot] = st;
val[tot] = v;
Prev[tot] = info[st % Hashmod];
info[st % Hashmod] = tot;
}
int st[maxn*maxn*2],cst[maxn*maxn*2],cnt_e;
int dfs(int nsta)
{
int tmp = 0;
if((tmp = Query(nsta)) != -1) return tmp;
tmp = 0;
for(int i=1;i<=cnt_e;i++)
if((nsta & st[i]) == st[i] && nsta < (st[i]<<1))
tmp = (tmp + 1ll * dfs(nsta ^ st[i]) * cst[i]%mod)%mod;
tmp = (tmp + mod) % mod;
Insert(nsta,tmp);
return tmp;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int tp,a,b,c,d;
scanf("%d",&tp);
scanf("%d%d",&a,&b);
a = a-1 , b = b-1 + n;
if(tp == 0)
{
st[++cnt_e] = (1<<a)|(1<<b);
cst[cnt_e] = inv2;
}
else
{
scanf("%d%d",&c,&d);
c=c-1,d=d-1+n;
st[++cnt_e] = (1<<a)|(1<<b);
cst[cnt_e] = inv2;
st[++cnt_e] = (1<<c)|(1<<d);
cst[cnt_e] = inv2;
if(st[cnt_e]&st[cnt_e-1]) continue;
st[++cnt_e] = (1<<a)|(1<<b)|(1<<c)|(1<<d);
cst[cnt_e] = tp == 1 ? inv4 : mod-inv4;
}
}
Insert(0,1);
printf("%lld\n",1ll*(1ll<<n)*dfs((1<<(2*n))-1)%mod);
}