Problem C. Dynamic Graph Matching
Time Limit: 8000/4000 MS (Java/Others)
Memory Limit: 524288/524288 K (Java/Others)
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
. Note that multiple edges between same pair of vertices are considered different.
Input
The first line of the input contains an integer
, denoting the number of test cases.
In each test case, there are 2 integers
mod
, denoting the number of vertices and operations.
For the next m lines, each line describes an operation, and it is guaranteed that
.
Output
For each operation, print a single line containing n2 integers, denoting the answer for
. Since the answer may be very large, please print the answer modulo
.
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
思路:设
表示前
次操作之后,
集合的点已经匹配的方案数。
对于加边操作,显然
。
这一维可以省略,从大到小遍历
。
对于删边操作,注意到加边操作的顺序不影响结果,可以假设第
次操作是加入要删除的边。
将加边操作的更新倒过来,得到:从小到大遍历
。
#include<bits/stdc++.h>
using namespace std;
const int MOD=1e9+7;
typedef long long ll;
int d[1<<10];
int ans[10];
int main()
{
int T;
cin>>T;
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
memset(d,0,sizeof d);
memset(ans,0,sizeof ans);
d[0]=1;
while(m--)
{
char op[3];
int x,y;
scanf("%s%d%d",op,&x,&y);
x--;
y--;
if(op[0]=='+')
{
for(int i=(1<<n)-1;i>=0;i--)
{
if((i&(1<<x))==0)continue;
if((i&(1<<y))==0)continue;
if(d[i^(1<<x)^(1<<y)]==0)continue;
(d[i]+=d[i^(1<<x)^(1<<y)])%=MOD;
}
}
else
{
for(int i=0;i<(1<<n);i++)
{
if((i&(1<<x))==0)continue;
if((i&(1<<y))==0)continue;
if(d[i^(1<<x)^(1<<y)]==0)continue;
(d[i]-=d[i^(1<<x)^(1<<y)])%=MOD;
(d[i]+=MOD)%=MOD;
}
}
for(int i=2;i<(1<<n);i++)
{
if(d[i]==0)continue;
(ans[__builtin_popcount(i)/2]+=d[i])%=MOD;
}
for(int i=1;i<=n/2;i++)printf("%d%c",ans[i],i==n/2?'\n':' ');
for(int i=1;i<=n/2;i++)ans[i]=0;
}
}
return 0;
}