HDU - 6321 Dynamic Graph Matching (状压dp)

版权声明:觉得好的话就给他人分享一下吧,欢迎转载,码字不容易啊,转载麻烦注明出处 https://blog.csdn.net/xiangAccepted/article/details/82684328

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对应的二进制个数]中。

扫描二维码关注公众号,回复: 4743317 查看本文章

参考博客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);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/xiangAccepted/article/details/82684328