Dynamic Graph Matching HDU - 6321 -边集合-状压DP

本文详细解析了HDU-6321问题中动态图匹配的算法实现,针对N个点的零图,在多次添加或删除边的操作下,计算不同匹配对的数量。采用二进制表示点集状态,通过一维数组dp进行匹配数的动态更新,实现高效求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  •  
  • Problem C. Dynamic Graph Matching

     HDU - 6321 
  • 题意:给定一个N个点的零图,M次操作,添加或删除一条边,每一次操作以后,打印用1,2,...N/2条边构成的匹配对数目。
  • 匹配对是指的 每条边连接的两个点,不能重复,例如  一共四个点 ,可以选择 1-2 一条边 3 -4 一条边 不能交叉
  •   两个点可以重复多条边,也就是 可以有 多个 1-2   被认为是不同的。
  • 思路:因为N的范围很小,所以可以把点的枚举状态用二进制表示集合。
  • 用一维数组dp[S]表示二进制集合为S的点集的匹配数。
  • 每次加边操作,遍历集合,dp[S]+=dp[S|(1<<u)&(1<<v)];删边操作,遍历集合dp[S]-=dp[S|(1<<u)&(1<<v)];。
  • 每个数对应二进制含有1的个数,每次记录答案就将每个dp[S]加到ans[S对应的二进制个数]中
  • #include<bits/stdc++.h>
    using namespace std;
    #define mod 1000000007
    #define maxn 1<<12
    int t,n,m,ans[15],tot,u,v;
    int dp[maxn],sum[maxn],ad;
    char op[5];
    int main()
    {
        for(int i=0; i<=(1<<11); i++)
            sum[i]=__builtin_popcount(i);
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&n,&m);
            tot=(1<<n);
            for(int i=0; i<tot; i++)
                dp[i]=0;
            dp[0]=1;
            while(m--)
            {
                scanf("%s%d%d",op,&u,&v);
                u--,v--;
                ad=((1<<u)|(1<<v));
                if(op[0]=='+')
                {
                    for(int i=0; i<tot; i++)
                        if((ad&i)==0)
                            dp[ad|i]=(dp[ad|i]+dp[i])%mod;
                }
                else
                {
                    for(int i=0; i<tot; i++)
                        if((ad&i)==0)
                            dp[ad|i]=(dp[ad|i]-dp[i]+mod)%mod;
                }
                memset(ans,0,sizeof(ans));
                for(int i=0; i<tot; i++)
                    ans[sum[i]]=(ans[sum[i]]+dp[i])%mod;
                for(int i=2; i<=n; i+=2)
                    if(i==n)printf("%d\n",ans[i]);
                    else printf("%d ",ans[i]);
            }
        }
        return 0;
    }
    
  •  
  •  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值