• 2018 Multi-University Training Contest 3 1003 / hdu6321 Problem C. Dynamic Graph Matching 状压dp


    Problem C. Dynamic Graph Matching

    题意:
    给定一个n个点的无向图,m次加边或者删边操作。在每次操作后统计有多少个匹配包含k= 1,2,...,n2条边。
    2≤n≤10,1≤m≤30000。 Shortest judge solution: 770 bytes
    题解:
    设f[i][S]表示前i次操作之后,S集合的点已经匹配的方案数。
    对于加边操作,显然f[i][S] =f[i−1][S] +f[i−1][S−u−v]。i这一维可以省略,从大到小遍历S,f[S]+ =[S−u−v]。
    对于删边操作,注意到加边操作的顺序不影响结果,可以假设第i−1次操作是加入要删除的边。
    将加边操作的更新倒过来,得到:从小到大遍历S,f[S]−=f[S−u−v]。
    时间复杂度O(m2n)。

    遍历顺序应该没有影响,因为 S 与 S-u-v 集合没有交集。

    
    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define rep(i,a,b) for (int i=a; i<=b; ++i)
    #define per(i,b,a) for (int i=b; i>=a; --i)
    #define mes(a,b)  memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define MP make_pair
    #define PB push_back
    #define fi  first
    #define se  second
    typedef long long ll;
    const int N = 200005, mod = 1e9+7;
    
    int cnt_1(int x) {
        int ret=0; for(int j=0; j<=9; ++j) if((x>>j)&1) ++ret; return ret;
    }
    int n, m, cnt1[3000];
    ll  ans[15], dp[3000];
    int main()
    {
        for(int i=0; i<(1<<10); ++i) cnt1[i] = cnt_1(i);
        int T;  scanf("%d", &T);
        while(T--)
        {
            mes(ans, 0);  mes(dp, 0);  dp[0]=1;
            scanf("%d%d", &n, &m);
            char ch;   int u, v;
            while(m--)
            {
                scanf("%*c%c%d%d", &ch, &u, &v);
                --u,  --v;
                int edge = (1<<u)|(1<<v);
                if(ch=='+') {
                    for(int i=(1<<n)-1; i>=0; --i)
                        if(cnt1[i&edge] == 2)
                            dp[i] = (dp[i]+dp[i-edge]+mod) %mod;
                }
                else {
                    for(int i=0; i<(1<<n); ++i)
                        if(cnt1[i&edge] == 2)
                            dp[i] = (dp[i]-dp[i-edge]+mod) %mod;
                }
                rep(i,0,14)  ans[i] = 0;
                for(int i=0; i<(1<<n); ++i)
                    ans[cnt1[i]] = (ans[cnt1[i]]+dp[i]+mod) %mod;
                for(int i=2; i<=n; i+=2)
                    printf("%lld%c", ans[i], " 
    "[i==n]);
            }
        }
    
        return 0;
    }
    
  • 相关阅读:
    ubuntu 右键添加出现 Open in terminal 选项
    03创建DataFrame的5种方法
    pandas——read_excel()方法学习
    Win10修改编辑hosts文件无法保存怎么办
    pandas插入一行记录
    python中的日期类型转换
    解决Ubuntu安装VM Tools请确保您已登录客户机操作系统。在客户机中装载CD驱动器启动终端,使用tar解压缩安装程序,然后执行vmware-insall.pl安装VMware Tools。
    怎么保存退出 vim 编辑
    反射
    Oracle
  • 原文地址:https://www.cnblogs.com/sbfhy/p/9410435.html
Copyright © 2020-2023  润新知