【HDU-6321】Dynamic Graph Matching 【状压DP】

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
分析:
‘+’ d p [ i ] [ S ] = d p [ i 1 ] [ S ] + d p [ i 1 ] [ S v u ] 当S中不包含v和u两个点
‘-’ d p [ i ] [ S ] = d p [ i 1 ] [ S ] d p [ i 1 ] [ S v u ] 当S中不包含v和u两个点
可以用滚动数组来优化,一般来说降掉一维之后dp的顺序很重要,但是这个题我们可以发现DP的顺序是无所谓的,因为当遍历到第i次操作的时候,当前层更新的永远是有(u,v)这两个点的集合状态,而且当前层利用的旧状态都是没有(u,v)这两个点的集合状态,所以DP顺序你可以随意确定,不会影响。

代码

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define bug(x)  cout<<"@@  "<<x<<"\n"

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const int N = (int) 1e6 + 11;
const int M = (int) 1e6 + 11;
const int INF = (int)0x3f3f3f3f;
const int MOD = (int)1e9 + 7;

#include <ext/rope>
using namespace __gnu_cxx;

inline void add(int &a, int b){ a = a + b < MOD ? a + b : a + b - MOD; } // %符号用多了很费时间,所以可以这样来优化一些
inline void sub(int &a, int b){ a = a - b >= 0 ? a - b : a - b + MOD; }

int cnt[1 << 10], ans[11], dp[1 << 10];
int main(){

    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        freopen("out.txt", "w", stdout);
    #endif

     int _; scanf("%d", &_);
     while(_--){
         int n, m; scanf("%d%d", &n, &m);
         for(int i = 0; i < (1 << n); i++) dp[i] = 0, cnt[i] = __builtin_popcount(i);
         dp[0] = 1;
         char s[10]; int a, b;
         while(m--){
             scanf("%s%d%d", s, &a, &b); a--; b--;
             int S = (1 << a) | (1 << b);
             for(int i = 0; i < (1 << n); i++){
                  if(!(i & S)){
                      if(s[0] == '+')
                         add(dp[ i ^ S], dp[i]);
                      else 
                          sub(dp[i ^ S], dp[i]);
                  }
             }
             memset(ans, 0, sizeof(int) * (n + 2));
             for(int i = 1; i < (1 << n); i++) add(ans[cnt[i]], dp[i]);
             for(int i = 2; i <= n; i += 2) printf("%d%c", ans[i], i < n ? ' ': '\n');
         }
     }
    return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_37383726/article/details/81319373