zoukankan      html  css  js  c++  java
  • 【BZOJ-4455】小星星 容斥 + 树形DP

    4455: [Zjoi2016]小星星

    Time Limit: 10 Sec  Memory Limit: 512 MB
    Submit: 204  Solved: 137
    [Submit][Status][Discuss]

    Description

    小Y是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品。她有n颗小星星,用m条彩色的细线串了起来,每条细线连着两颗小星星。有一天她发现,她的饰品被破坏了,很多细线都被拆掉了。这个饰品只剩下了n?1条细线,但通过这些细线,这颗小星星还是被串在一起,也就是这些小星星通过这些细线形成了树。小Y找到了这个饰品的设计图纸,她想知道现在饰品中的小星星对应着原来图纸上的哪些小星星。如果现在饰品中两颗小星星有细线相连,那么要求对应的小星星原来的图纸上也有细线相连。小Y想知道有多少种可能的对应方式。只有你告诉了她正确的答案,她才会把小饰品做为礼物送给你呢。

    Input

    第一行包含个2正整数n,m,表示原来的饰品中小星星的个数和细线的条数。
    接下来m行,每行包含2个正整数u,v,表示原来的饰品中小星星u和v通过细线连了起来。
    这里的小星星从1开始标号。保证u≠v,且每对小星星之间最多只有一条细线相连。
    接下来n-1行,每行包含个2正整数u,v,表示现在的饰品中小星星u和v通过细线连了起来。
    保证这些小星星通过细线可以串在一起。
    n<=17,m<=n*(n-1)/2

    Output

    输出共1行,包含一个整数表示可能的对应方式的数量。
    如果不存在可行的对应方式则输出0。

    Sample Input

    4 3
    1 2
    1 3
    1 4
    4 1
    4 2
    4 3

    Sample Output

    6

    HINT

    Source

    Solution

    一道容斥的好题

    我们一共要满足两个限制:1.树中的一个点对应图中一个点,且一一对应  2.树中两点有边的,图中两点也对应有边

    首先我们考虑最暴力的方法,如果同时满足两个限制,用$O(N^{N})$的时间去枚举,然后计数

    那如果我们放宽一个限制,只统计满足限制2的数目,这显然可以用树形DP在$O(N^{3})$的时间里得到的

    这里得到的是有$K$个点可以映射,但不保证$K$个点都被映射到,且不保证每个点只被映射一次

    那么考虑用容斥去统计出答案,答案就是$Ans(N)-Ans(N-1)+Ans(N-2)-Ans(N-3)+Ans(N-4).....$

    这样容斥的时候的枚举是$O(2^{N})$的

    所以总的复杂度是$O(2^{N}×N^{3})$的

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    #define LL long long
    #define MAXN 50
    int N,M;
    struct EdgeNode{int next,to;}edge[MAXN<<1];
    int head[MAXN],cnt=1;
    void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
    void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);}
    LL dp[MAXN][MAXN],ans,now,tmp;
    int lt[MAXN][MAXN],bin[MAXN],tot,a[MAXN];
    void DFS(int now,int last)
    {
        for (int i=head[now]; i; i=edge[i].next)
            if (edge[i].to!=last) DFS(edge[i].to,now);
        for (int i=1; i<=tot; i++)
            {
                dp[now][i]=1;
                for (int j=head[now]; j; j=edge[j].next)
                    if (edge[j].to!=last)
                        {
                            tmp=0;
                            for (int k=1; k<=tot; k++)
                                if (lt[a[k]][a[i]]) tmp+=dp[edge[j].to][k];
                            dp[now][i]*=tmp;
                        }
            }
    }
    int main()
    {
        N=read(),M=read();
        for (int x,y,i=1; i<=M; i++) x=read(),y=read(),lt[x][y]=lt[y][x]=1;
        for (int x,y,i=1; i<=N-1; i++) x=read(),y=read(),InsertEdge(x,y);
        bin[0]=1; for (int i=1; i<=N; i++) bin[i]=bin[i-1]<<1;
        for (int i=1; i<=bin[N]-1; i++)
            {
                now=0; tot=0;
                for (int j=1; j<=N; j++) if (i&bin[j-1]) a[++tot]=j;
                DFS(1,0);
                for (int j=1; j<=tot; j++) now+=dp[1][j];
                if ((tot&1)==(N&1)) ans+=now; else ans-=now;            
            }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    动态生成 Excel 文件供浏览器下载的注意事项
    JavaEE 中无用技术之 JNDI
    CSDN 泄露用户密码给我们什么启示
    刚发布新的 web 单点登录系统,欢迎下载试用,欢迎提建议
    jQuery jqgrid 对含特殊字符 json 数据的 Java 处理方法
    一个 SQL 同时验证帐号是否存在、密码是否正确
    PostgreSQL 数据库在 Windows Server 2008 上安装注意事项
    快速点评 Spring Struts Hibernate
    Apache NIO 框架 Mina 使用中出现 too many open files 问题的解决办法
    解决 jQuery 版本升级过程中出现 toLowerCase 错误 更改 doctype
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5793086.html
Copyright © 2011-2022 走看看