Problem C. Dynamic Graph Matching
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 1662 Accepted Submission(s): 677
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 | We have carefully selected several similar problems for you: 6343 6342 6341 6340 6339
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#include<stack>
#include<string.h>
#include<stdlib.h>
#include<cstdio>
#define ll long long
#define MAX 1000000000
#define ms memset
using namespace std;
const int maxn=1e5+5;
const int mod=1e9+7;
/*
题目大意:给定m个操作,
可以加边可以减边。
对于每一次操作输出1到n/2的数量的匹配计数。
由于数据量只有10,考虑状态压缩,
假定s是当前点的状态,
那么加边操作是如果状态s里均没有
x和y两点,那么计数状态dp[新状态]+=dp[s];
减边操作对应着减法。
*/
int n,m;
int x,y,s;
int dp[maxn],ans[15];
int num[3000];
char c;
int main()
{
for(int i=0;i<=1024;i++) num[i]=num[i>>1]+(i&1);
int t;scanf("%d",&t);
while(t--)
{
memset(dp,0,sizeof(dp));
s=0,dp[s]=1;
scanf("%d%d",&n,&m);getchar();
for(int i=0;i<m;i++)
{
scanf("%c",&c);getchar();
scanf("%d%d",&x,&y);getchar();
x--,y--;
s|=(1<<x) , s|=(1<<y);
if(c=='+')
{
for(int i=0;i<=s;i++)
if((i&(1<<x))==0 && (i&(1<<y))==0)
dp[i^(1<<x)^(1<<y)]=(dp[i^(1<<x)^(1<<y)]+dp[i])%mod;
}
else
{
for(int i=0;i<=s;i++)
if((i&(1<<x))==0 && (i&(1<<y))==0)
dp[i^(1<<x)^(1<<y)]=(dp[i^(1<<x)^(1<<y)]-dp[i]+mod)%mod;
}
memset(ans,0,sizeof(ans));
for(int i=0;i<=s;i++) ans[num[i]/2]+=dp[i],ans[num[i]/2]%=mod;
for(int i=1;i<=n/2;i++) printf("%d%c",ans[i],((i==n/2)?'\n':' '));
}
}
return 0;
}