hdu6321 /// 状压DP
题目大意:
将一个 顶点不重复的边 的边集称为图中的matching
在一个n个点的零图中进行m次操作
+ u v为在u v之间加一条边 存在重边
- u v为去掉u v之间的一条边
每次操作后 输出边集大小为1 2 3 ... n/2的有多少%(1e9+7)
https://www.cnblogs.com/xiuwenli/p/9398342.html
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; #define LL long long #define INF 0x3f3f3f3f #define mem(i,j) memset(i,j,sizeof(i)) #define inc(i,l,r) for(int i=l;i<=r;i++) #define dec(i,r,l) for(int i=r;i>=l;i--) const int N=(1<<10)+5; const int mod=1e9+7; int n,m; LL ans[10+5]; LL cnt[N],dp[N]; int main() { int _; scanf("%d",&_); while(_--) { scanf("%d%d",&n,&m); int task=(1<<10)-1; inc(i,0,task) cnt[i]=__builtin_popcount(i); // i二进制有多少1 mem(dp,0); dp[0]=1LL; while(m--) { char s[3]; int u,v; scanf("%s%d%d",s,&u,&v); u--, v--; int now=(1<<u)|(1<<v); if(s[0]=='+') { inc(i,0,task) if((i&now)==0) dp[i|now]=(dp[i|now]+dp[i])%mod; } else { inc(i,0,task) if((i&now)==0) dp[i|now]=(dp[i|now]-dp[i]+mod)%mod; } mem(ans,0); inc(i,0,task) ans[cnt[i]]=(ans[cnt[i]]+dp[i])%mod; inc(i,2,n) { printf("%lld",ans[i]); if(i==n) printf("\n"); else printf(" "); i++; } // 边集为1对应2个点 2对应4个点 3对应6个点 } } return 0; }