zoukankan      html  css  js  c++  java
  • uoj185 [ZJOI2016]小星星 【dp + 容斥】

    题目链接

    uoj185

    题解

    (f[i][j])表示(i)为根的子树,(i)号点对应图上(j)号点时的方案数
    显然这样(dp)会使一些节点使用同一个节点,此时总的节点数就不满(n)

    我们枚举选的点(S),再进行(dp)
    然后根据选的点数量进行容斥

    【BZOJ卡不过QAQ】

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define mp(a,b) make_pair<int,int>(a,b)
    #define cls(s) memset(s,0,sizeof(s))
    #define cp pair<int,int>
    #define LL long long int
    #define lbt(x) (x & -x)
    using namespace std;
    const int maxn = 18,maxm = 100005,INF = 1000000000;
    inline int read(){
        int out = 0,flag = 1; char c = getchar();
        while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
        while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
        return out * flag;
    }
    int n,m,fa[maxn],S,G[maxn][maxn],g[maxn][maxn];
    LL f[maxn][maxn];
    void dfs(int u){
        LL sum;
        for (int i = 1; i <= n; i++)
            if ((S & (1 << i - 1))) f[u][i] = 1;
            else f[u][i] = 0;
        for (int to = 1; to <= n; to++) if (g[u][to] && to != fa[u]){
            fa[to] = u; dfs(to);
            for (int i = 1; i <= n; i++) if (f[u][i]){
                sum = 0;
                for (int j = 1; j <= n; j++)
                    sum += f[to][j] * G[i][j];
                f[u][i] *= sum;
            }
        }
    }
    int main(){
        n = read(); m = read(); int a,b;
        REP(i,m){
            a = read(); b = read();
            G[a][b] = G[b][a] = 1;
        }
        for (int i = 1; i < n; i++){
        	a = read(); b = read();
        	g[a][b] = g[b][a] = 1;
        }
        int maxv = (1 << n) - 1,cnt;
        LL sum,ans = 0;
        for (S = 1; S <= maxv; S++){
            cnt = 0; for (int i = S; i; i -= lbt(i)) cnt++;
            dfs(1); sum = 0;
            for (int i = 1; i <= n; i++) sum += f[1][i];
            if ((n - cnt) & 1) ans -= sum;
            else ans += sum;
        }
        printf("%lld
    ",ans);
        return 0;
    }
    
    
  • 相关阅读:
    家长如何助力孩子适应小学生活
    一年级线上家长会
    gdb常用调试命令
    二叉树-后序遍历
    机器人
    Oracle创建只读账号的详细步骤
    ORACLE RAC日常运维-调整RAC+DG环境redo大小
    Redis 延迟分析
    oracle dataguard 重启步骤
    catalog start with + switch database to copy的妙用
  • 原文地址:https://www.cnblogs.com/Mychael/p/9044690.html
Copyright © 2011-2022 走看看