hdu 6321 Dynamic Graph Matching (状态压缩)

http://acm.hdu.edu.cn/showproblem.php?pid=6321

题意:给一个图有N个点和若干个询问,每个询问增或者删一条边,每个询问输出选择1~N/2条不相交的边的方案数。

思路:因为n=10,我们可以用状态压缩来做处理这道题,如果加了这条边,那么这条边的两个端点的二进制位置都表示为1。

每次加入一条边 a,b 那么如果某个i的二进制 a–和b–对应位置都为1,那么也就是说这个状态可以由i-(1<

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
#define ll long long
ll dp[1111];
int cnt[1111];
ll ans[11];
void init()
{
    memset(cnt,0,sizeof(cnt));
    for(int i=1;i<=1023;i++)
    {
        int x=i;
        int f=0;
        while(x)
        {
            if(x&1)f++;
            x>>=1;
        }

        cnt[i]=f;
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    char c[5];
    int x,y;
    init();
    while(T--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        memset(dp,0,sizeof(dp));
        memset(ans,0,sizeof(ans));
        dp[0]=1;
        while(m--)
        {
            scanf("%s%d%d",&c,&x,&y);
            x--,y--;
            if(c[0]=='+')
            {
                for(int i=(1<<x)|(1<<y);i<(1<<n);i++)
                {
                    if(i&(1<<x)&&i&(1<<y)&&cnt[i]%2==0)
                    {
                        dp[i]=(dp[i]+dp[i-(1<<x)-(1<<y)])%mod;
                        ans[cnt[i]]=(ans[cnt[i]]+dp[i-(1<<x)-(1<<y)])%mod;
                    }
                }
            }
            else
            {
                for(int i=(1<<x)|(1<<y);i<(1<<n);i++)
                {
                    if(i&(1<<x)&&i&(1<<y)&&cnt[i]%2==0)
                    {
                        dp[i]=(dp[i]-dp[i-(1<<x)-(1<<y)]+mod)%mod;
                        ans[cnt[i]]=(ans[cnt[i]]-dp[i-(1<<x)-(1<<y)]+mod)%mod;
                    }
                }
            }
            for(int i=2;i<=n;i+=2)
            {
                if(i>2)printf(" ");
                printf("%lld",ans[i]);
            }
            printf("\n");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/imzxww/article/details/81475556