http://acm.hdu.edu.cn/showproblem.php?pid=6321
POINT:
其实这题很简单。匹配的点状压就行了。
然后DP就是最基本的背包差不多。
加一条边,就是加一对匹配的点。u,v。
状态包含1<<u和1<<v的dp[x]+=dp[x-1<<u-1<<v]就行了。
减的话差不多,就-=。
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
#define LL long long
using namespace std;
const int mod = 1e9+7;
int dp[2000];
int ans[2000];
int one[2000];
int clc1(int x)
{
int ans=0;
while(x){
if(x&1) ans++;
x>>=1;
}
return ans;
}
int n,m;
void pf()
{
for(int i=1;i<n/2;i++)
printf("%d ",ans[2*i]);
printf("%d\n",ans[n]);
}
int main()
{
int T;
scanf("%d",&T);
for(int i=0;i<(1<<10);i++) one[i]=clc1(i);
while(T--){
memset(dp,0,sizeof dp);
memset(ans,0,sizeof ans);
scanf("%d%d",&n,&m);
dp[0]=1;
while(m--){
char s[3];
int u,v;
scanf("%s%d%d",s,&u,&v);
u--;v--;
u=1<<u;v=1<<v;
if(s[0]=='+'){
for(int i = (1<<10)-1;i>=0;i--){
if((i&u)&&(i&v)&&dp[i-u-v]!=0){
dp[i]+=dp[i-u-v];
ans[one[i]]+=dp[i-u-v];
dp[i]%=mod;ans[one[i]]%=mod;
}
}
}else{
for(int i = (1<<10)-1;i>=0;i--){
if((i&u)&&(i&v)&&dp[i-u-v]!=0){
dp[i]-=dp[i-u-v];
ans[one[i]]-=dp[i-u-v];
dp[i]=(dp[i]+mod)%mod;
ans[one[i]]=(ans[one[i]]+mod)%mod;
}
}
}
pf();
}
}
return 0;
}