• HDU


    题意:给定一个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对应的二进制个数]中。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn =1030;
    const int mod = 1e9+7;
    typedef long long LL;
    void add(int &a,int b){a=a+b<mod?a+b:a+b-mod;}
    void del(int &a,int b){a=a-b<0?a-b+mod:a-b;}
    int dp[maxn],ans[15],cnt[maxn];
    
    int main()
    {
        #ifndef ONLINE_JUDGE
             freopen("in.txt","r",stdin);
             freopen("out.txt","w",stdout);
        #endif
        int T,N,M,u,v;
        char op[5];
        scanf("%d",&T); 
        while(T--){
            scanf("%d%d",&N,&M);
            int tot=1<<N;
            for(int i=0;i<tot;++i){
                dp[i]=0;
                cnt[i] = __builtin_popcount(i);
            }
            dp[0]=1;
            while(M--){
                scanf("%s%d%d",op,&u,&v);
                memset(ans,0,sizeof(ans));
                u--,v--;
                int S = (1<<u)|(1<<v);                  //取只包含u,v的集合
                if(op[0]=='+'){
                    for(int t=tot-1;~t;--t)
                        if(!(t&S)) add(dp[t^S],dp[t]);  //加上原来不包含的u,v的集合的匹配数
                }
                else{
                    for(int t=0;t<tot;++t)
                        if(!(t&S)) del(dp[t^S],dp[t]);  //减去原来不包含u,v的集合的匹配数
                }
                for(int i=1;i<tot;++i) add(ans[cnt[i]],dp[i]);
                for(int i=2;i<=N;i+=2) printf("%d%c",ans[i],i<N?' ':'
    ');
            }
        }
        return 0;
    }
    为了更好的明天
  • 相关阅读:
    关于HTML Table标签的边框问题总结
    Java编程中-servlet
    编程语言简史
    SQL SERVER 数据库操作脚本
    JQuery实现方法,简单示例
    001-python基础-python安装和升级
    .cs文件与aspx.cs文件之间的区别是什么???他们的作用是什么???ASPX文件的作用是什么?
    判读字符串长度
    <%=id%>是什么意思
    sql中复合组建解析
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9398342.html
Copyright © 2020-2023  润新知