Problem C. Dynamic Graph Matching Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others) Total Submission(s): 1215 Accepted Submission(s): 505 Problem Description In the mathematical discipline of graph theory, a matching in a graph is a set of edges without common vertices. You are given an undirected graph with n vertices, labeled by 1,2,...,n. Initially the graph has no edges. There are 2 kinds of operations : + u v, add an edge (u,v) into the graph, multiple edges between same pair of vertices are allowed. - u v, remove an edge (u,v), it is guaranteed that there are at least one such edge in the graph. Your task is to compute the number of matchings with exactly k edges after each operation for k=1,2,3,...,n2. Note that multiple edges between same pair of vertices are considered different. Input The first line of the input contains an integer T(1≤T≤10), denoting the number of test cases. In each test case, there are 2 integers n,m(2≤n≤10,nmod2=0,1≤m≤30000), denoting the number of vertices and operations. For the next m lines, each line describes an operation, and it is guaranteed that 1≤u<v≤n. Output For each operation, print a single line containing n2 integers, denoting the answer for k=1,2,3,...,n2. Since the answer may be very large, please print the answer modulo 109+7. Sample Input 1 4 8 + 1 2 + 3 4 + 1 3 + 2 4 - 1 2 - 3 4 + 1 2 + 3 4 Sample Output 1 0 2 1 3 1 4 2 3 1 2 1 3 1 4 2 Source 2018 Multi-University Training Contest 3 Recommend chendu Statistic | Submit | Discuss | Note
装压dp
+:操作很简单就是:dp[i]+=dp[i-(1<<u)-(1<<v)];
-:操作就想象成反的: dp[i]-=dp[i-(1<<u)-(1<<v)];拿总的减去用到用到u,v
类似于背包某个物品不能放;
#include <cstdio> #include <cstring> #include <iostream> //#include <algorithm> #include <vector> using namespace std; #define ll long long //#define mod 998244353 const int mod=1e9+7; ll dp[1<<11];//dp[i]:i集合内点完全匹配的方案数 int bit[1<<11];//i的二进制的1个数; ll ans[11]; int lowbit(int x) {return x&-x;} int calc(int x) { int res=0; while(x){res++;x=x-lowbit(x);} return res; } int main() { for(int i=0;i<(1<<10);i++) bit[i]=calc(i); int T,n,m,u,v; char op[3]; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); memset(dp,0,sizeof dp); memset(ans,0,sizeof ans); dp[0]=1; while(m--) { scanf("%s%d%d",op,&u,&v); u--;v--; if(op[0]=='+') { for(int i=(1<<n)-1;i>0;i--) if(((1<<u)&i)&&((1<<v)&i)) { dp[i]+=dp[i-(1<<u)-(1<<v)]; ans[bit[i]]+=dp[i-(1<<u)-(1<<v)]; //对于i集合所有点的匹配,会对ans造成的影响 dp[i]=dp[i]%mod; ans[bit[i]]=ans[bit[i]]%mod; } } else { for(int i=1;i<1<<n;i++) if(((1<<u)&i)&&((1<<v)&i)) { dp[i]-=dp[i-(1<<u)-(1<<v)]; ans[bit[i]]-=dp[i-(1<<u)-(1<<v)]; dp[i]=(dp[i]+mod)%mod; ans[bit[i]]=(ans[bit[i]]+mod)%mod; } } for(int i=2;i<=n;i=i+2) { if(i!=2) cout<<" "; printf("%lld",ans[i]); } cout<<endl; } } return 0; }