HDU 6321 Dynamic Graph Matching 状压DP

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zy704599894/article/details/81315812

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

题意:有n个点m次操作,每次操作有两种

+ x y:表示添加一条边x-y

- x y:表示删除一条边x-y

问包含k条边,且没有一个点与两条边相连的匹配有多少种,重复的边算作不同。

dp[i]表示当前状态为i的情况有多少种,i的二进制有哪几位是1就表示选择那些点。每当添加或删除一条边x-y时,假设所有包含点x和y的状态为now,则不包含点x和y的状态为pre=now^((1<<(x-1))|(1<<(y-1))),dp[now]可由dp[rev]转移,添加是dp[now]+=dp[pre],删除时dp[now]-=dp[pre]。所有二进制k位1的状态存入ans[k]输出。

#include<cstdio>
#include<stdio.h>
#include<string.h>
using namespace std;
#define ll long long
const int maxm = (1 << 10);
const int mod = 1e9 + 7;
char str[maxm];
ll dp[maxm], ans[maxm], s[maxm];
int main()
{
	int n, i, j, k, sum, t, m, e, x, y;
	for (i = 1;i < (1 << 10);i++)
		for (j = 10;j >= 0;j--)
			if ((i&(1 << j)) != 0)
				s[i]++;
	scanf("%d", &t);
	while (t--)
	{
		scanf("%d%d", &n, &m);
		e = (1 << n);
		memset(dp, 0, sizeof(dp));
		dp[0] = 1;
		for (j = 1;j <= m;j++)
		{
			scanf("%s%d%d", str, &x, &y);
			x--, y--;
			int now = (1 << x) | (1 << y);
			if (str[0] == '+')
			{
				for (i = 0;i < e;i++)
					if ((i&now) == 0)
						dp[i | now] = (dp[i | now] + dp[i]) % mod;
			}
			else
			{
				for (i = 0;i < e;i++)
					if ((i&now) == 0)
						dp[i|now] = (dp[i|now] - dp[i] + mod) % mod;
			}
			for (i = 1;i <= n;i++) ans[i] = 0;
			for (i = 1;i < e;i++)
				ans[s[i]] = (ans[s[i]] + dp[i]) % mod;
			for (i = 2;i <= n;i += 2)
				printf("%lld%c", ans[i], (i < n) ? ' ' : '\n');
		}
	}
}

猜你喜欢

转载自blog.csdn.net/zy704599894/article/details/81315812