这状压dp还是比较好的。。思维上有点难度。。。
目标是使该点连的黑/白边数为度数的一半。。考虑到度数不超过8,那么边数自然也不超过4,所以只要用2位二进制来表示连的黑边数。。
然后转移就可以随便转移。。主要是在二进制部分位的提取和替换。。
/** * ┏┓ ┏┓ * ┏┛┗━━━━━━━┛┗━━━┓ * ┃ ┃ * ┃ ━ ┃ * ┃ > < ┃ * ┃ ┃ * ┃... ⌒ ... ┃ * ┃ ┃ * ┗━┓ ┏━┛ * ┃ ┃ Code is far away from bug with the animal protecting * ┃ ┃ 神兽保佑,代码无bug * ┃ ┃ * ┃ ┃ * ┃ ┃ * ┃ ┃ * ┃ ┗━━━┓ * ┃ ┣┓ * ┃ ┏┛ * ┗┓┓┏━━━━━━━━┳┓┏┛ * ┃┫┫ ┃┫┫ * ┗┻┛ ┗┻┛ */ #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> #include<cmath> #include<map> #include<stack> #include<set> #define inc(i,l,r) for(int i=l;i<=r;i++) #define dec(i,l,r) for(int i=l;i>=r;i--) #define link(x) for(edge *j=h[x];j;j=j->next) #define mem(a) memset(a,0,sizeof(a)) #define ll long long #define eps 1e-12 #define succ(x) (1<<x) #define lowbit(x) (x&(-x)) #define sqr(x) ((x)*(x)) #define mid (x+y>>1) #define NM 205 #define nm 100005 #define pi 3.1415926535897931 const ll inf=1000000007; using namespace std; ll read(){ ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return f*x; } int n,m,c[nm],d[nm],_x,_y,s,tot,b[NM]; int main(){ int _=read();while(_--){ n=read();m=read();mem(c);mem(b);mem(d); tot=succ(n*2)-1;s=0; c[0]=1; inc(i,1,m){ _x=read();_y=read();b[_x]++;b[_y]++; inc(j,0,tot)if(c[j]){ int x=2*!!(j&succ(2*_x-1))+!!(j&succ(2*_x-2)); int y=2*!!(j&succ(2*_y-1))+!!(j&succ(2*_y-2)); int dx=(j&succ(2*_x-1))+(j&succ(2*_x-2)); int dy=(j&succ(2*_y-1))+(j&succ(2*_y-2)); //printf("%d %d %d %d %d\n",j,dx,dy,x,y); x++;y++; if(x<5&&y<5)d[j^dx^dy^(x*succ(2*_x-2))^(y*succ(2*_y-2))]+=c[j]; } inc(j,0,tot)c[j]=d[j]+c[j],d[j]=0; } bool f=false; inc(i,1,n)if(b[i]%2){f=true;break;}else s+=(b[i]/2)*succ(i*2-2); if(!f)printf("%d\n",c[s]);else printf("0\n"); } return 0; }