1. 程式人生 > >HDU - 6321 Dynamic Graph Matching (狀壓dp)

HDU - 6321 Dynamic Graph Matching (狀壓dp)

Problem C. Dynamic Graph Matching
Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 2138    Accepted Submission(s): 872


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

 

題意:給定一個N個點的無向圖,M次操作,新增或刪除一條邊,每一次操作以後,列印用1,2,...N/2條邊構成的匹配數。

思路:因為N的範圍很小,所以可以把點的列舉狀態用二進位制表示集合。用一維陣列dp[S]表示二進位制集合為S的點集的匹配數。每次加邊操作,從大到小遍歷集合(對後面的狀態不產生影響),dp[S]+=dp[S-u-v](請細細品味這個狀態轉移);刪邊操作,從小到大遍歷集合,dp[S]-=dp[S-u-v]。預處理出每個1024之內每個數對應二進位制含有1的個數,每次記錄答案就將每個dp[S]加到ans[S對應的二進位制個數]中。

參考部落格http://www.cnblogs.com/xiuwenli/p/9398342.html

程式碼:

#include<stack>
#include<queue>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define inf 0x3f3f3f3f
#define LL long long
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
const LL mod=1e9+7;
const LL N=1e3+100;
LL dp[N],ans[15],cnt[N];
int main()
{
    LL T;
    scanf("%lld",&T);
    while(T--)
    {
        mem(dp,0);
        mem(ans,0);
        mem(cnt,0);
        dp[0]=1;
        LL n,m;
        char s[5];
        LL x,y;
        scanf("%lld%lld",&n,&m);
        LL k=1<<n;
        for(LL i=0; i<k; i++)
        {
            LL x=i;
            while(x)
            {
                if(x&1) cnt[i]++;
                x>>=1;
            }
        }
        while(m--)
        {
            scanf("%s%lld%lld",s,&x,&y);
            x--,y--;
            LL S=(1<<x)|(1<<y);
            if(s[0]=='+')
            {
                for(LL i=k-1; ~i; i--)
                    if(!(S&i))  dp[S^i]=(dp[S^i]+dp[i])%mod;
            }
            else
            {
                for(LL i=0; i<k; i++)
                    if(!(S&i))  dp[S^i]=(dp[S^i]-dp[i]+mod)%mod;
            }
            for(LL i=0; i<k; i++)  ans[cnt[i]]+=dp[i];
            for(LL i=2; i<=n; i+=2)
            {
                if(i!=2) printf(" ");
                printf("%lld",ans[i]%mod);
            }
            printf("\n");
            mem(ans,0);
        }
    }
}