BZOJ 4455: [Zjoi2016]小星星 [容斥原理 树形DP]

本文解析了[Zjoi2016]小星星问题,通过使用容斥原理和树形DP算法,解决了图到树的点对应方案计数问题。详细介绍了如何通过容斥原理简化复杂度,并给出了具体实现代码。

4455: [Zjoi2016]小星星

题意:一个图删掉一些边形成一棵树,告诉你图和树的样子,求让图上的点和树上的点对应起来有多少方案


看了很多题解又想了一段时间,感觉题解都没有很深入,现在大致有了自己的想法吧

如果直接上树形DP的话,必须要保存当前子树对应了图上的点的集合才行,要不然做不到1对1.但这样复杂度就炸掉了至少需要\(3^n\)枚举子集

我们可以用容斥原理来弱化这个限制,使得允许多对1
\[ 树上n个点对应图上n个点的方案数\ = \\ \]
\[ n个点对应\le n个点\ -\ n个点对应\le n-1个点\ + n个点对应\le n-2个点\ ... \]
对应\(\le i\)个点的方案数很好求啊,没有了1对1的限制,直接枚举i个点的集合树形DP就可以了\(O(n^3)\)

总的复杂度\(O(n^32^n)\),貌似还需要卡一下常

再说一点,这里没有必要想之前\(\ge k\)的容斥原理题一样乘上一个组合数去掉统计方案数时重复了,因为n是全部

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=50;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

int n, m, x, y, g[N][N], a[N], p;
struct edge{int v, ne;}e[N];
int cnt, h[N];
inline void ins(int u, int v) {
    e[++cnt]=(edge){v, h[u]}; h[u]=cnt;
    e[++cnt]=(edge){u, h[v]}; h[v]=cnt;
}

ll f[N][N];
void dfs(int u, int fa) {
    for(int j=1; j<=p; j++) f[u][j]=1;
    for(int i=h[u];i;i=e[i].ne) if(e[i].v != fa) {
        int v=e[i].v;
        dfs(v, u);
        for(int j=1; j<=p; j++) {
            ll t=0;
            for(int k=1; k<=p; k++) if(g[a[j]][a[k]]) t += f[v][k];
            f[u][j] *= t;
        }
    }
}
int main() {
    freopen("in","r",stdin);
    n=read(); m=read();
    for(int i=1; i<=m; i++) x=read(), y=read(), g[x][y]=g[y][x]=1;
    for(int i=1; i<n; i++) ins(read(), read());
    int All=1<<n;
    ll ans=0;
    for(int s=1; s<All; s++) {
        p=0; ll t=0;
        for(int i=0; i<n; i++) if(s&(1<<i)) a[++p]=i+1;
        dfs(1, 0);
        for(int i=1; i<=p; i++) t+=f[1][i];
        if((n-p)&1) ans -= t;
        else ans += t;
    }
    printf("%lld\n",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值