【链接】
http://acm.hdu.edu.cn/showproblem.php?pid=6321
【题意】
一开始图是空的,总共有m个操作,每次可以添加或者删除一条边,每个操作结束后,输出这个图里面匹配数为1,2,...,n/2的方案数
数据范围:n<=10,m<=300000
【方法】
状压dp。每操作一条边,计算贡献,显然是不包含这两个点的所有状态,用二进制表示枚举即可。
【思路】
#include<bits/stdc++.h>
#define ll long long
//const int maxn = 1e7 + 5;
using namespace std;
const int maxn = 1 << 10;
const int mod = 1e9 + 7;
ll dp[maxn];
ll ans[12];
char op;
inline int cal(int n) {
bitset<10>a(n);
return a.count();
}
inline void ff(int x, int y) {
for (int s = 0; s < maxn; ++s) {
if ((s&(1 << x)) || (s&(1 << y)))continue;
int S = s | (1 << x) | (1 << y);
if (op == '+') {
dp[S] += dp[s];
dp[S] %= mod;
ans[cal(S)] = (ans[cal(S)] + dp[s]) % mod;
}
else {
dp[S] = (dp[S] - dp[s] + mod) % mod;
ans[cal(S)] = (ans[cal(S)] - dp[s] + mod) % mod;
}
}
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
memset(dp, 0, sizeof(dp));
memset(ans, 0, sizeof(ans));
int n, m;
dp[0] = 1;
scanf("%d%d", &n, &m);
while (m--) {
int x, y;
getchar();
scanf("%c %d%d", &op, &x, &y);
x--; y--;
ff(x, y);
for (int i = 2; i <= n; i+=2) {
if (i != 2)printf(" ");
printf("%lld", ans[i]);
}
printf("\n");
}
}
}