bzoj 4455: [Zjoi2016]小星星

Posted Nico&11101001

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 4455: [Zjoi2016]小星星相关的知识,希望对你有一定的参考价值。

链接

http://www.lydsy.com/JudgeOnline/problem.php?id=4455

 

dp+容斥题意大约是树上的点满足与图上的点一一对应并且图中两两有边,树中也两两有边,求满足条件的方案数

只保证在树在图中两两有边,用dp[i][j]表示树上i点被映射到图中的j点,以i为根的子树方案数,那么方案数可以用dp在$O(n^3)$时间内处理出来

我们把1设为树的根,那么就可以得方案数$\sum\limits_{i=1}^n f(1,i) $

这时的方案数是有重复的,考虑容斥

答案就是ans(n)−ans(n1)+ans(n2)−ans(n3)+ans(n4).....

我们可以二进制枚举他的子集进行容斥复杂度$O(2^n)$

总复杂度O(2^nn^3)

这道题就做完了

#include<cstdio>
#include<cstring>

const int maxn = 50;
const int MAXN=1e6+10;
inline char nc()
{
    static char buf[MAXN],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
    char c=nc();int x=0;
    while(c<0||c>9)c=nc();
    while(c>=0&&c<=9)x=x*10+c-0,c=nc();
    return x;
}

struct node{
    int v,next;
}edge[maxn*4];
int n,m,num;
int map[maxn*maxn][maxn*maxn],head[maxn];
inline void add_edge(int u,int v) {
    edge[++num].v=v;edge[num].next=head[u];head[u]=num;
}
int node_num=0;
int node[maxn];long long dp[maxn][maxn];
void dfs(int x,int fa) {
    for(int i=1;i<=n;++i)dp[x][node[i]]=1;
    for(int i=head[x];i;i=edge[i].next) {
        int v=edge[i].v;
        if(v==fa)continue;
        dfs(v,x);
        for(int j=1;j<=node_num;++j) {
            long long cnt=0;
            for(int k=1;k<=node_num;++k) 
                if(map[node[j]][node[k]])
                    cnt+=dp[v][node[k]];
            dp[x][node[j]]*=cnt;
        }

    }
    
}
int main() {
    n=read(),m=read();
    long long ans=0;
    for(int a,b,i=1;i<=m;++i) {
        a=read(),b=read();
        map[a][b]=map[b][a]=1;
    }
    for(int a,b,i=1;i<n;++i) {
        a=read(),b=read();
        add_edge(a,b);
        add_edge(b,a);
    }
    for(int i=1;i<(1<<n);++i) {
        node_num=0;
        for(int j=1;j<=n;++j) {
            if((1<<j-1)&i)node[++node_num]=j;
        }
        dfs(1,1);
        long long tot=0;
        for(int j=1;j<=node_num;++j) 
            tot+=dp[1][node[j]];
        if((node_num&1)==(n&1))ans+=tot;
        else ans-=tot;
    }
    printf("%lld\n",ans);
    return 0;
}

 

以上是关于bzoj 4455: [Zjoi2016]小星星的主要内容,如果未能解决你的问题,请参考以下文章

bzoj4455ZJOI2016小星星

bzoj 4455: [Zjoi2016]小星星

BZOJ 4455 [Zjoi2016]小星星 容斥计数

BZOJ4455: [Zjoi2016]小星星

4455[Zjoi2016]小星星 容斥+dp

4455: [Zjoi2016]小星星|状压DP|容斥原理