bzoj4455 [Zjoi2016]小星星(容斥原理+状压枚举+树形dp)

首先我们有一个树形状压dp的想法,f[x][i][S]表示x节点,匹配原图的i节点,子树匹配了原图S状态的点的方案数,这样可以保证一一对应,不重不漏,可惜复杂度高达 O(n33n) O ( n 3 3 n ) ,无法承受。
我们考虑容斥,用树上n个点匹配原图n个点的所有方案-匹配原图n-1个点的所有方案+匹配原图n-2个点的所有方案-…
于是我们 O(2n) O ( 2 n ) 枚举原图的一个点集,树形dp来计算方案数(f[x][i]表示x节点,匹配原图的i节点且子树均匹配上的方案数),然后乘上容斥系数扔到答案里。
复杂度 O(2nn3) O ( 2 n n 3 ) ,仔细算一下其实是 i=1nCini3 ∑ i = 1 n C n i i 3 ,还不到1e8

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 20
inline char gc(){
    static char buf[1<<16],*S,*T;
    if(T==S){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
int n,m,bin[N],h[N],num=0,a[N],tot;
ll f[N][N],ans=0;
bool mp[N][N];
struct edge{
    int to,next;
}data[N<<1];
inline void dfs(int x,int Fa){
    for(int i=1;i<=tot;++i) f[x][i]=1;
    for(int i=h[x];i;i=data[i].next){
        int y=data[i].to;if(y==Fa) continue;dfs(y,x);
        for(int j=1;j<=tot;++j){
            ll res=0;
            for(int k=1;k<=tot;++k) res+=mp[a[j]][a[k]]*f[y][k];
            f[x][j]*=res;
        }
    }
}
int main(){
//  freopen("a.in","r",stdin);
    n=read();m=read();bin[0]=1;
    for(int i=1;i<=n;++i) bin[i]=bin[i-1]<<1;
    for(int i=1;i<=m;++i){
        int x=read(),y=read();mp[x][y]=mp[y][x]=1;
    }for(int i=1;i<n;++i){
        int x=read(),y=read();
        data[++num].to=y;data[num].next=h[x];h[x]=num;
        data[++num].to=x;data[num].next=h[y];h[y]=num;
    }for(int S=1;S<bin[n];++S){
        tot=0;for(int i=0;i<n;++i) if(S&bin[i]) a[++tot]=i+1;
        dfs(1,0);ll res=0;for(int i=1;i<=tot;++i) res+=f[1][i];
        ans+=((n-tot)&1)?-res:res;
    }printf("%lld\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值